上一篇文章【实现简易 ES6 Promise 功能 (一)】实现了基本的异步功能。今天咱们接着上次的内容继续扯,如何实现【数据传递】以及当【回调函数返回一个新的promise】segmentfault
上篇已完成的代码数组
function Promise(func){ this.state = 'pending'; this.doneList = []; func(this.resolve.bind(this)); } Promise.prototype = { resolve: function(){ while(true){ if( this.doneList.length === 0 ){ this.state = 'done'; break; } this.doneList.shift().apply(this); } }, then: function(callback){ this.doneList.push(callback); if( this.state === 'done'){ this.state = 'pending'; this.resolve(); } return this; } }
测试代码promise
new Promise(function(resolve){ resolve(1) }).then(function(data){ console.log(data); // 1 return 2; }).then(function(data){ console.log(data); // 2 });
上面的结果,就是咱们要实现的。resolve的参数(只传递第一个参数,若是有)传递给第一个then里面函数做为参数,第一个then里面的函数返回值传递给第二个then里面的函数做为参数,以此类推。app
关键代码异步
resolve: function(){ // arguments[0]是resolve的第一个参数 while(true){ if( this.doneList.length === 0 ){ this.state = 'done'; break; } // 这里是运行then里面回调函数的地方 this.doneList.shift().apply(this); } }
如何修改呢?除了第一次传递参数,是把resolve的参数往下传递,其他的都是把上次的结果做为下次开始(参数)。
因而,咱们能够先把上次doneList里面的函数运行结果保存起来。而后,等到下次须要的时候,再传给下一个回调函数。
代码修改:函数
resolve: function(){ // arguments[0]是resolve的第一个参数 var arg = arguments[0]; while(true){ if( this.doneList.length === 0 ){ this.state = 'done'; break; } // 这里是运行then里面回调函数的地方 // 以数组形式传给下一个函数,而后保存新的值 // 判断传递的参数是否为undefined,是的话,就不用传了 if( typeof arg === 'undefined' ){ arg = this.doneList.shift().apply(this); }else{ arg = this.doneList.shift().apply(this, [arg]); } } // 保存最后的arg,保证后续的回调能继续获得参数 this.arg = arg; } // 还须要修改then方法 then: function(callback){ this.doneList.push(callback); if( this.state === 'done'){ this.state = 'pending'; this.resolve(this.arg); // 注意这里也要传递参数 } return this; }
第一次修改完善的代码,及测试结果测试
function Promise(func){ this.state = 'pending'; this.doneList = []; func(this.resolve.bind(this)); } Promise.prototype = { resolve: function(){ // arguments[0]是resolve的第一个参数 var arg = arguments[0]; while(true){ if( this.doneList.length === 0 ){ this.state = 'done'; break; } // 这里是运行then里面回调函数的地方 // 以数组形式传给下一个函数,而后保存新的值 // 判断传递的参数是否为undefined,是的话,就不用传了 if( typeof arg === 'undefined' ){ arg = this.doneList.shift().apply(this); }else{ arg = this.doneList.shift().apply(this, [arg]); } } // 保存最后的arg,保证后续的回调能继续获得参数 this.arg = arg; }, then: function(callback){ this.doneList.push(callback); if( this.state === 'done'){ this.state = 'pending'; this.resolve(this.arg); // 注意这里也要传递参数 } return this; } } // 测试 new Promise(function(resolve){ resolve(1) }).then(function(data){ console.log(data); // 1 return 2; }).then(function(data){ console.log(data); // 2 });
结果截图:this
今天的第一个功能已经完了,那么如今开始开发第二个功能。spa
先看一个测试prototype
new Promise(function(resolve){ resolve(1) }).then(function(data){ console.log(data, 2); // 1,2 return new Promise(function(resolve){ window.setTimeout(function(){ resolve(3); }, 1000); }).then(function(data){ console.log(data, 4); // 3,4 return 5; }); }).then(function(data){ console.log(data, 6); // 5, 6 });
测试结果
我在上面测试例子中,then回调函数中返回的promise中故意使用了延迟函数。可是,输出结果中5日后传了,而且[5,6]是在[3,4]以后,且都有一秒中的延迟。
若是没有回调返回一个promise,程序会一直按照第一行走下去,就算回调中有其余promise(只要不return),也是两条并行的线。一旦返回promise,新的promise会在这个点插入,而且原来尚未执行的回调,也会排到新的回调列表后面了。
先来修改resolve方法,由于回调函数都是在这里运行的。
resolve: function(){ // arguments[0]是resolve的第一个参数 var arg = arguments[0]; while(true){ if( this.doneList.length === 0 ){ this.state = 'done'; break; } /*************************/ if( arg instanceof Promise ){ // 把新的promise保存起来,待会要用 this.promise = arg; // 本promise没有执行完的回调所有加入到新的回调列表 arg.doneList = arg.doneList.concat(this.doneList); // 改变回调及状态 this.doneList.length = 0; this.state = 'done'; // 跳出循环 break; } /*************************/ // 这里是运行then里面回调函数的地方 // 以数组形式传给下一个函数,而后保存新的值 // 判断传递的参数是否为undefined,是的话,就不用传了 if( typeof arg === 'undefined' ){ arg = this.doneList.shift().apply(this); }else{ arg = this.doneList.shift().apply(this, [arg]); } } // 保存最后的arg,保证后续的回调能继续获得参数 this.arg = arg; } then: function(callback){ this.doneList.push(callback); if( this.state === 'done'){ this.state = 'pending'; this.resolve(this.arg); // 注意这里也要传递参数 } // 这里不能在返回this了,而是一个promise对象 return this.promise; } // 若是then没有返回promise,那么this.promise = this; function Promise(func){ this.state = 'pending'; this.doneList = []; func(this.resolve.bind(this)); // 默认指向自己 this.promise = this; }
本期完整代码
function Promise(func){ this.state = 'pending'; this.doneList = []; func(this.resolve.bind(this)); this.promise = this; } Promise.prototype = { resolve: function(){ // arguments[0]是resolve的第一个参数 var arg = arguments[0]; while(true){ if( this.doneList.length === 0 ){ this.state = 'done'; break; } if( arg instanceof Promise ){ this.promise = arg; arg.doneList = arg.doneList.concat(this.doneList); this.doneList.length = 0; this.state = 'done'; break; } // 这里是运行then里面回调函数的地方 // 以数组形式传给下一个函数,而后保存新的值 // 判断传递的参数是否为undefined,是的话,就不用传了 if( typeof arg === 'undefined' ){ arg = this.doneList.shift().apply(this); }else{ arg = this.doneList.shift().apply(this, [arg]); } } // 保存最后的arg,保证后续的回调能继续获得参数 this.arg = arg; }, then: function(callback){ this.doneList.push(callback); if( this.state === 'done'){ this.state = 'pending'; this.resolve(this.arg); // 注意这里也要传递参数 } return this.promise; } }
结束。谢谢你们阅读,若有错误或建议请给我留言或者发私信。