使用Promise解决多层异步调用的简单学习心得(2)

如果onFulfilled返回的是一个普通的值,那么then函数会返回一个默认的Promise变量。执行这个Promise的then函数会使Promise立即被满足,执行onFulfilled函数,而这个onFulfilled的入参,即是上一个onFulfilled的返回值。

而如果onFulfilled返回的是一个Promise变量,那个这个Promise变量就会作为then函数的返回值。

关于then函数和onFulfilled函数的返回值的这一系列设定,MDN和MSDN上的文档都没有明确的正面描述,至于ES6官方文档ECMAScript 2015 (6th Edition, ECMA-262)。。。我的水平有限实在看不懂,如果哪位高手能解释清楚官方文档里面对着两个返回值的描述,请一定留言指教!!!

所以以上为我的自由发挥,语言组织的有点拗口,上代码看一下大家就明白了。

首先是返回普通变量的情况:

new Promise(function(res, rej) { console.log(Date.now() + " start setTimeout 1"); setTimeout(res, 2000); }).then(function() { console.log(Date.now() + " timeout 1 call back"); return 1024; }).then(function(arg) { console.log(Date.now() + " last onFulfilled return " + arg); });

以上代码执行结果为:

$ node promisTest.js 1450277122125 start setTimeout 1 1450277124129 timeout 1 call back 1450277124129 last onFulfilled return 1024

有点意思对不对,但这不是关键。关键是onFulfilled函数返回一个Promise变量可以使我们很方便的连续调用多个异步过程。比如我们可以这样来尝试连续做两个延时操作:

new Promise(function(res, rej) { console.log(Date.now() + " start setTimeout 1"); setTimeout(res, 2000); }).then(function() { console.log(Date.now() + " timeout 1 call back"); return new Promise(function(res, rej) { console.log(Date.now() + " start setTimeout 2"); setTimeout(res, 3000); }); }).then(function() { console.log(Date.now() + " timeout 2 call back"); });

执行结果如下:

$ node promisTest.js 1450277510275 start setTimeout 1 1450277512276 timeout 1 call back 1450277512276 start setTimeout 2 1450277515327 timeout 2 call back

如果觉得这也没什么了不起,那再多来几次也不在话下:

new Promise(function(res, rej) { console.log(Date.now() + " start setTimeout 1"); setTimeout(res, 2000); }).then(function() { console.log(Date.now() + " timeout 1 call back"); return new Promise(function(res, rej) { console.log(Date.now() + " start setTimeout 2"); setTimeout(res, 3000); }); }).then(function() { console.log(Date.now() + " timeout 2 call back"); return new Promise(function(res, rej) { console.log(Date.now() + " start setTimeout 3"); setTimeout(res, 4000); }); }).then(function() { console.log(Date.now() + " timeout 3 call back"); return new Promise(function(res, rej) { console.log(Date.now() + " start setTimeout 4"); setTimeout(res, 5000); }); }).then(function() { console.log(Date.now() + " timeout 4 call back"); });

$ node promisTest.js 1450277902714 start setTimeout 1 1450277904722 timeout 1 call back 1450277904724 start setTimeout 2 1450277907725 timeout 2 call back 1450277907725 start setTimeout 3 1450277911730 timeout 3 call back 1450277911730 start setTimeout 4 1450277916744 timeout 4 call back

可以看到,多个延时的回调函数被有序的排列下来,并没有出现喜闻乐见的金字塔状结构。虽然代码里面调用的都是异步过程,但是看起来就像是全部由同步过程构成的一样。这就是Promise带给我们的好处。

如果你有把啰嗦的代码提炼成单独函数的好习惯,那就更加画美不看了:

function timeout1() { return new Promise(function(res, rej) { console.log(Date.now() + " start timeout1"); setTimeout(res, 2000); }); } function timeout2() { return new Promise(function(res, rej) { console.log(Date.now() + " start timeout2"); setTimeout(res, 3000); }); } function timeout3() { return new Promise(function(res, rej) { console.log(Date.now() + " start timeout3"); setTimeout(res, 4000); }); } function timeout4() { return new Promise(function(res, rej) { console.log(Date.now() + " start timeout4"); setTimeout(res, 5000); }); } timeout1() .then(timeout2) .then(timeout3) .then(timeout4) .then(function() { console.log(Date.now() + " timout4 callback"); });

$ node promisTest.js 1450278983342 start timeout1 1450278985343 start timeout2 1450278988351 start timeout3 1450278992356 start timeout4 1450278997370 timout4 callback

接下来我们可以再继续研究一下onFulfilled函数传入入参的问题。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzpfzs.html