理解Promise的3种姿势

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

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

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


// 示例1

function asyncFunc()

{

return new Promise(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

function asyncFunc()

{

return new Promise(function(resolve, reject)

{

setTimeout(function()

{

resolve(‘Hello, Fundebug!‘);

}, 1000);

});

}

async function main()

{

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

function asyncFunc()

{

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

function asyncFunc()

{

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所绑定的回调函数,这其实就是事件。

参考

版权声明:
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/09/25/3-ways-to-understand-promise/
时间: 2024-10-03 20:19:23

理解Promise的3种姿势的相关文章

CSDN日报20170224——《程序员该用哪种姿势来理财》

[程序人生] 程序员该用哪种姿势来理财 作者:纯洁的虫子 其实一直想写一篇文章名字都想好了,叫做"程序员该不该理财?".后来想了想,该不该这个就不用想了,必须要理财! 那么市面上那么多理财的方式对于我们屌丝的程序员该如何选择呢? 其实我也是那种土的掉渣的那种类型,以前几乎没有想过神马理财的,一来呢毕业的时候工资全都不够花的还理个毛线,二来总是感觉理财好像都是有钱人搞的东西:后来偶然进入了互联网金融行业,呆了几年,慢慢也接触了很多理财方式,但也还是一个门外汉,此文就是和大家一起聊聊我们程

HDU1233 - 还是畅通工程 最小生成树,用了三种姿势AC

HDU1233 - 还是畅通工程 : http://acm.hdu.edu.cn/showproblem.php?pid=1233 用了三种姿势AC这题之后, 感觉对最小生成树的理解又更深了一层. 嗯, 让你们看看我用的是哪三种姿势 方法 1 : #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const in

160701、理解 Promise 的工作原理

Javascript 采用回调函数(callback)来处理异步编程.从同步编程到异步回调编程有一个适应的过程,但是如果出现多层回调嵌套,也就是我们常说的厄运的回调金字塔(Pyramid of Doom),绝对是一种糟糕的编程体验.于是便有了 CommonJS 的 Promises/A 规范,用于解决回调金字塔问题.本文先介绍 Promises 相关规范,然后再通过解读一个迷你的 Promises 以加深理解. 什么是 Promise   一个 Promise 对象代表一个目前还不可用,但是在未

补习系列-springboot 实现拦截的五种姿势

目录 简介 姿势一.使用 Filter 接口 1. 注册 FilterRegistrationBean 2. @WebFilter 注解 姿势二.HanlderInterceptor 姿势三.@ExceptionHandler 注解 姿势四.RequestBodyAdvice/ResponseBodyAdvice RequestBodyAdvice 的用法 ResponseBodyAdvice 用法 姿势五.@Aspect 注解 思考 小结 简介 AOP(面向切面编程)常用于解决系统中的一些耦合

【bzoj3224】Tyvj 1728 普通平衡树 平衡树的三种姿势 :splay,Treap,ScapeGoat_Tree

直接上代码 正所谓 人傻自带大常数 平衡树的几种姿势:  AVL Red&Black_Tree 码量爆炸,不常用:SBT 出于各种原因,不常用. 常用: Treap 旋转 基于旋转操作和随机数堆 但不支持区间操作. 非旋转 基于随机数堆和拆分合并操作 常数较大 Spaly 完全基于旋转 各种操作 ScapeGoat_Tree 基于a权值平衡树和压扁重构 无旋转 但不支持区间操作 PS:非旋转可以实现平衡树的可持久化,从而来套一些东西 splay #include<cstdio> #de

HDU 2089 不要62(数位DP,三种姿势)

HDU 2089 不要62(数位DP,三种姿势) ACM 题目地址:HDU 2089 题意: 中文题意,不解释. 分析: 100w的数据,暴力打表能过 先初始化dp数组,表示前i位的三种情况,再进行推算 直接dfs,一遍搜一变记录,可能有不饥渴的全部算和饥渴的部分算情况,记录只能记录全部算(推荐看∑大的详细题解Orz) 代码: 1. 暴力 (以前写的) /* * Author: illuz <iilluzen[at]gmail.com> * File: 2089_bf.cpp * Create

快速理解VirtualBox的四种网络连接方式

VirtualBox中有4中网络连接方式: NAT Bridged Adapter Internal Host-only Adapter VMWare中有三种,其实他跟VMWare 的网络连接方式都是一样概念,只是比VMWare多了Internal方式. 要让自己(或别人)理解深刻,方法就是做比较和打比方,比较之间的不同和相同,拿熟知的事物打比方.先来一张图,通过这张图就很容易看出这4种方式的区别: (注:此图直接取至Finalbug的Blog,表示感谢) 再来用文字做详细的解释(其实归结起来就

两个文件去重的N种姿势

最近利用shell帮公司优化挖掘关键词的流程,用shell替代了多个环节的操作,极大提高了工作效率. shell在文本处理上确有极大优势,比如多文本合并.去重等,但是最近遇到了一个难搞的问题,即两个大数据量文件去重. 有txt文件A.txt和B.txt. 其中A为关键词和搜索量,以逗号分隔,约90万行. B为关键词,约400万行. 需要从A中找出与B重复的关键词. 我试了N种姿势,但结果都不尽人意,最奇怪的是有些方法对小数据量的测试文件有用,一旦用在A与B上就会失败,真叫人百思不得其解. 姿势一

快速了解IOC的几种姿势

一.首先我们了解IOC如何注入的几种姿势 构造函数注入(Constructor Injection) Ioc容器会智能的选择和调用合适的构造函数以创建依赖的对象.如果被选择的构造函数具有相应的参数,Ioc容器在调用构造函数之前解析注册的依赖关系并自行初始化获得相应的参数对象. 属性注入(Property  Injection) 通过[Dependency]标记为依赖属性,在创建对象时,依赖属性对象会被IOC容器自行获取相应的对象. 方法注入(Method Injection) 通过[Inject