自己写一个Promise
2019-04-30 23:41:06来源:博客园 阅读 ()
参考Promise 的 官方规范 https://promisesaplus.com/
Promise 其实就是一个状态机
它只有两种状态变化 pending =》 fulfilled
pending =》 rejected
并且状态一旦发生变化后就不会再改变
我们用es5来实现下
先写个架子, 并测试下:
function myPromise(executor) { var _this = this; // 保存当前的函数上下文 _this.status = 'pending'; // 初始状态 _this.resolveValue = null; // resolve初始值 _this.rejectValue = null; // reject初始值 function resolve(value) { if (_this.status == 'pending') { _this.status = 'Fulfilled'; _this.resolveValue = value; } } function reject(reason) { if (_this.status == 'pending') { _this.status = 'Fulfilled'; _this.rejectValue = reason; } } try { // 捕获错误 executor(resolve, reject) } catch (e){ reject(e); } } myPromise.prototype.then = function (onFulfilled, onRejected) { var _this = this; if (_this.status == 'Fulfilled') { onFulfilled(_this.resolveValue) } if (_this.status == 'Rejected') { onRejected(_this.rejectValue) } }; var p = new myPromise((resolve, reject) => { resolve('I am handsome'); throw Error('捕获错误') }); p.then((data) => { console.log(data) }, (err) => { console.log(err) } );
结果:
它先执行resolve 状态 变为 Fulfilled ,
然后报错 ,执行reject , 由于此时状态不是pending, 状态还是Fulfilled
Promise的核心是处理异步,
现在我们的代码并不能等待状态的改变,
接下来我们加上处理异步操作的功能, 并测试下
function myPromise(executor) { var _this = this; // 保存当前的函数上下文 _this.status = 'pending'; // 初始状态 _this.resolveValue = null; // resolve初始值 _this.rejectValue = null; // reject初始值 _this.resolveCallbackList = []; // 存resolve的回调 _this.rejectCallbackList = []; // 存reject的回调 function resolve(value) { if (_this.status == 'pending') { _this.status = 'Fulfilled'; _this.resolveValue = value; // 状态改变执行存的回调 _this.resolveCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } function reject(reason) { if (_this.status == 'pending') { _this.status = 'Rejected'; _this.rejectValue = reason; // 状态改变执行存的回调 _this.rejectCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } try { // 捕获错误 executor(resolve, reject) } catch (e){ reject(e); } } myPromise.prototype.then = function (onFulfilled, onRejected) { var _this = this; if (_this.status == 'Fulfilled') { onFulfilled(_this.resolveValue) } if (_this.status == 'Rejected') { onRejected(_this.rejectValue) } // 等待状态时把回调存起来,状态改变再触发 if (_this.status == 'pending') { _this.resolveCallbackList.push(function () { onFulfilled(_this.resolveValue) }); _this.rejectCallbackList.push(function () { onRejected(_this.rejectValue) }); } }; var p = new myPromise((resolve, reject) => { setTimeout(() => { resolve('I am handsome'); }, 0); // throw Error('捕获错误') }); p.then((data) => { console.log(data) }, (err) => { console.log(err) } );
结果:
?? 它已经能处理异步操作了
接下来实现链式操作, 再测试下
function myPromise(executor) { var _this = this; // 保存当前的函数上下文 _this.status = 'pending'; // 初始状态 _this.resolveValue = null; // resolve初始值 _this.rejectValue = null; // reject初始值 _this.resolveCallbackList = []; // 存resolve的回调 _this.rejectCallbackList = []; // 存reject的回调 function resolve(value) { if (_this.status == 'pending') { _this.status = 'Fulfilled'; _this.resolveValue = value; // 状态改变执行存的回调 _this.resolveCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } function reject(reason) { if (_this.status == 'pending') { _this.status = 'Rejected'; _this.rejectValue = reason; // 状态改变执行存的回调 _this.rejectCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } try { // 捕获错误 executor(resolve, reject) } catch (e){ reject(e); } } myPromise.prototype.then = function (onFulfilled, onRejected) { var _this = this; // 用于链式调用 var nextPromise = new myPromise(function(res, rej) { if (_this.status == 'Fulfilled') { // 存一下回调执行的结果,传给下一个.then var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); } if (_this.status == 'Rejected') { // 存一下回调执行的结果,传给下一个.then var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); } // 等待状态时把回调存起来,状态改变再触发 if (_this.status == 'pending') { _this.resolveCallbackList.push(function () { // 存一下回调执行的结果,传给下一个.then var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); }); _this.rejectCallbackList.push(function () { var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); }); } }); return nextPromise }; var p = new myPromise((resolve, reject) => { setTimeout(() => { resolve('I am handsome'); }, 0); // throw Error('捕获错误') }); p.then((data) => { console.log(data + ' suc' + ' 1') return 222 }, (err) => { console.log(err) } ).then((data) => { console.log(data + ' suc' + ' 2') }, (err) => { console.log(err) } );
结果 :
没毛病, 可以链式调用then了 , 先不处理返回值为Promise 的 情况 ,
原生的Promise 执行方法都是异步的 , 并且执行方法是能捕捉错误,
我们加上这个功能 , 并且测试下
function myPromise(executor) { var _this = this; // 保存当前的函数上下文 _this.status = 'pending'; // 初始状态 _this.resolveValue = null; // resolve初始值 _this.rejectValue = null; // reject初始值 _this.resolveCallbackList = []; // 存resolve的回调 _this.rejectCallbackList = []; // 存reject的回调 function resolve(value) { if (_this.status == 'pending') { _this.status = 'Fulfilled'; _this.resolveValue = value; // 状态改变执行存的回调 _this.resolveCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } function reject(reason) { if (_this.status == 'pending') { _this.status = 'Rejected'; _this.rejectValue = reason; // 状态改变执行存的回调 _this.rejectCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } try { // 捕获错误 executor(resolve, reject) } catch (e){ reject(e); } } myPromise.prototype.then = function (onFulfilled, onRejected) { var _this = this; // 用于链式调用 var nextPromise = new myPromise(function(res, rej) { if (_this.status == 'Fulfilled') { // 存一下回调执行的结果,传给下一个.then setTimeout(function () { // 捕获错误 try { var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); } catch (e) { rej(e) } },0) } if (_this.status == 'Rejected') { // 存一下回调执行的结果,传给下一个.then setTimeout(function () { // 捕获错误 try { var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); } catch (e) { rej(e) } },0) } // 等待状态时把回调存起来,状态改变再触发 if (_this.status == 'pending') { _this.resolveCallbackList.push(function () { // 存一下回调执行的结果,传给下一个.then setTimeout(function () { // 捕获错误 try { var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); } catch (e) { rej(e) } },0) }); _this.rejectCallbackList.push(function () { setTimeout(function () { // 捕获错误 try { var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); } catch (e) { rej(e) } },0) }); } }); return nextPromise }; var p = new myPromise((resolve, reject) => { setTimeout(() => { resolve('I am handsome'); console.log(111) }, 0); // throw Error('捕获错误') }); p.then((data) => { console.log(data + ' suc' + ' 1'); throw Error('bao cuo') }, (err) => { console.log(err + ' err' + ' 1') } ).then((data) => { console.log(data + ' suc' + ' 2') }, (err) => { console.log(err + ' err' + ' 2') } ); console.log(222);
预期结果 222 =》 111 =》 I am handsome suc 1 =》 Error: bao cuo err 2
实际结果:
没毛病, 异步并且捕获到错误了
我们再来处理 空 then() 就是then里面不传参数的情况, 并测试
myPromise.prototype.then = function (onFulfilled, onRejected) { // 参数为空把值直接传给下一个then if (!onFulfilled) { onFulfilled = function (val) { return val; } } if (!onRejected) { onRejected = function (val) { return new Error(val) } } var _this = this; // 用于链式调用 var nextPromise = new myPromise(function(res, rej) { if (_this.status == 'Fulfilled') { // 存一下回调执行的结果,传给下一个.then setTimeout(function () { // 捕获错误 try { var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); } catch (e) { rej(e) } },0) } if (_this.status == 'Rejected') { // 存一下回调执行的结果,传给下一个.then setTimeout(function () { // 捕获错误 try { var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); } catch (e) { rej(e) } },0) } // 等待状态时把回调存起来,状态改变再触发 if (_this.status == 'pending') { _this.resolveCallbackList.push(function () { // 存一下回调执行的结果,传给下一个.then setTimeout(function () { // 捕获错误 try { var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); } catch (e) { rej(e) } },0) }); _this.rejectCallbackList.push(function () { setTimeout(function () { // 捕获错误 try { var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); } catch (e) { rej(e) } },0) }); } }); return nextPromise }; var p = new myPromise((resolve, reject) => { setTimeout(() => { resolve('I am handsome'); }, 0); // throw Error('捕获错误') }); p.then((data) => { console.log(data + ' suc' + ' 1'); throw Error('bao cuo') }, (err) => { console.log(err + ' err' + ' 1') } ).then( ).then((data) => { console.log(data + ' suc' + ' 3') }, (err) => { console.log(err + ' err' + ' 3') } );
结果:
?? 第一个then里抛出的错误被第三个then 接受到了, 没毛病
接下来处理 返回值为promise的情况, 并测试
如果返回值为promise,后面的then就取决于返回的promise的状态
// 处理返回值的函数 function ResolutionRetrunPromise (nextPromise, returnValue, res, rej) { // 返回值是否是promise if (returnValue instanceof myPromise) { returnValue.then(function (val) { res(val) },function (reason) { rej(reason) }) } else { res(returnValue) } } myPromise.prototype.then = function (onFulfilled, onRejected) { // 参数为空把值直接传给下一个then if (!onFulfilled) { onFulfilled = function (val) { return val; } } if (!onRejected) { onRejected = function (reason) { return new Error(reason) } } var _this = this; // 用于链式调用 var nextPromise = new myPromise(function(res, rej) { if (_this.status == 'Fulfilled') { // 存一下回调执行的结果,传给下一个.then setTimeout(function () { // 捕获错误 try { var nextResolveValue = onFulfilled(_this.resolveValue); // 处理返回值 ResolutionRetrunPromise(nextPromise, nextResolveValue, res, rej) // res(nextResolveValue); } catch (e) { rej(e) } },0) } if (_this.status == 'Rejected') { // 存一下回调执行的结果,传给下一个.then setTimeout(function () { // 捕获错误 try { var nextRejectValue = onRejected(_this.rejectValue); ResolutionRetrunPromise(nextPromise, nextRejectValue, res, rej) // rej(nextRejectValue); } catch (e) { rej(e) } },0) } // 等待状态时把回调存起来,状态改变再触发 if (_this.status == 'pending') { _this.resolveCallbackList.push(function () { // 存一下回调执行的结果,传给下一个.then setTimeout(function () { // 捕获错误 try { var nextResolveValue = onFulfilled(_this.resolveValue); ResolutionRetrunPromise(nextPromise, nextResolveValue, res, rej) // res(nextResolveValue); } catch (e) { rej(e) } },0) }); _this.rejectCallbackList.push(function () { setTimeout(function () { // 捕获错误 try { var nextRejectValue = onRejected(_this.rejectValue); ResolutionRetrunPromise(nextPromise, nextRejectValue, res, rej) // rej(nextRejectValue); } catch (e) { rej(e) } },0) }); } }); return nextPromise }; var p = new myPromise((resolve, reject) => { setTimeout(() => { resolve('I am handsome'); }, 1000); }); p.then((data) => { console.log(data + ' suc' + ' 1'); return new myPromise((resolve, reject) => { reject('promise') }) }, (err) => { console.log(err + ' err' + ' 1') } ).then((data) => { console.log(data + ' suc' + ' 3') }, (err) => { console.log(err + ' err' + ' 3') } );
结果:
到此 Promise 的 基本功能就实现了 ,
感兴趣的同学可以基于此 自己实现一下Promise 的 静态方法 。 。 。 。。 。
原文链接:https://www.cnblogs.com/LHLVS/p/10796751.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
下一篇:3-2 路由_路由对象详解
- jQuery异步提交表单的两种方式 2020-03-12
- 默认让页面的第一个控件选中的javascript代码 2020-02-20
- 将数组扁平化并去除其中重复数据,最终得到一个升序且不重复 2019-08-14
- vue.js(4)--字符串跑马灯 2019-08-14
- es6学习笔记(二) 2019-08-14
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash