stefanzan分享 http://blog.sciencenet.cn/u/stefanzan

博文

理解Promise的3种姿势

已有 1807 次阅读 2017-9-26 13:38 |系统分类:科研笔记| promise

译者按: 对于Promise,也许你会用了,却并不理解;也许你理解了,却只可意会不可言传。这篇博客将从3个简单的视角理解Promise,应该对你有所帮助。

为了保证可读性,本文采用意译而非直译,并且对源代码进行了大量修改。另外,本文版权归原作者所有,翻译仅用于学习。

示例1中,asyncFunc()函数返回的是一个Promise实例:

// 示例1
functionasyncFunc()
{
returnnewPromise(function(resolve, reject)
{
       setTimeout(function()
{
           resolve('Hello, Fundebug!');
       }, 100);
   });
}
asyncFunc()
   .then(function(x)
{
console.log(x); // 1秒之后打印"Hello, Fundebug!"
   });

1秒之后,Promise实例的状态变为resolved,就会触发then绑定的回调函数,打印resolve值,即”Hello, Fundebug!”。

那么,什么是Promise呢?

  • Promise调用是阻塞的

  • Promise中保存了异步操作结果

  • Promise是一个事件

Promise调用是阻塞的

示例2可以帮助我们理解阻塞

// 示例2
functionasyncFunc()
{
returnnewPromise(function(resolve, reject)
{
       setTimeout(function()
{
           resolve('Hello, Fundebug!');
       }, 1000);
   });
}
asyncfunctionmain()
{
const x = await asyncFunc(); // (A)
console.log(x); // (B) 1秒之后打印"Hello, Fundebug!"
}
main();

以上代码是采用Async/Await语法写的,与示例1完全等价。await的中文翻译即为”等待”,这里可以”望文生义”。因此,相比于使用Promise实现,它更加直观地展示了什么是阻塞

  • (A)行: 等待asyncFunc()执行,直到它返回结果,并赋值给变量x

  • (B)行: 打印x

事实上,使用Promise实现时,也需要等待asyncFunc()执行,之后再调用then绑定的回调函数。因此,调用Promise时,代码也是阻塞的。

Promise中保存了异步操作结果

如果某个函数返回Promise实例,则这个Promise最初相当于一个空白的容器,当函数执行结束时,其结果将会放进这个容器。示例3通过数组模拟了这个过程:

// 示例3
functionasyncFunc()
{
const blank = [];
   setTimeout(function()
{
       blank.push('Hello, Fundebug!');
   }, 1000);
return blank;
}
const blank = asyncFunc();
console.log(blank);  // 打印"[]"
setTimeout(function()
{
const x = blank[0]; // (A)
console.log(x); // 2秒之后打印"Hello, Fundebug!"
}, 2000);

开始时,blank为空数组,1秒之后,”Hello, Fundebug!”被添加到数组中,为了确保成功,我们需要在2秒之后从blank数组中读取结果。

对于Promise,我们不需要通过数组或者其他变量来传递结果,then所绑定的回调函数可以通过参数获取函数执行的结果。

Promise是一个事件

示例4模拟了事件:

// 示例4
functionasyncFunc()
{
const eventEmitter = {
       success: []
   };
   setTimeout(function()
{
for (const handler of eventEmitter.success)
       {
           handler('Hello, Fundebug!');
       }
   }, 1000);
return eventEmitter;
}
asyncFunc()
   .success.push(function(x)
{
console.log(x); // 1秒之后打印"Hello, Fundebug!"
   });

调用asyncFunc()之后,sucesss数组其实是空的,将回调函数push进数组,相当于绑定了事件的回调函数。1秒之后,setTimeout定时结束,则相当于事件触发了,这时sucess数组中已经注册了回调函数,于是打印”Hello, Fundebug!”。

Promise成功resolve时,会触发then所绑定的回调函数,这其实就是事件。

参考







https://blog.sciencenet.cn/blog-811611-1077831.html

上一篇:我从Angular 2转向Vue.js, 也没有选择React
下一篇:我的高质量软件发布心得
收藏 IP: 211.143.155.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-4-20 11:19

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部