译者按: 对于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

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了7亿+错误事件,得到了Google、360、金山软件、百姓网等众多知名用户的认可。欢迎免费试用!

版权声明

转载时请注明作者Fundebug以及本文地址:

https://blog.fundebug.com/2017/09/25/3-ways-to-understand-promise/

理解Promise的三种姿势的更多相关文章

  1. 理解Promise的3种姿势

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

  2. 理解java的三种代理模式

    代理模式是什么 代理模式是一种设计模式,简单说即是在不改变源码的情况下,实现对目标对象的功能扩展. 比如有个歌手对象叫Singer,这个对象有一个唱歌方法叫sing(). 1 public class ...

  3. 举例理解Hibernate的三种状态

    初学Hibernate,了解到Hibernate有三种状态:transient(瞬时状态),persistent(持久化状态)以及detached(游离状态). 它们之间有如下转换图来说明: 1.tr ...

  4. 一个简单的例子理解Kubernetes的三种IP地址类型

    很多Kubernetes的初学者对Kubernetes里面三种不同的IP地址和工作机制理解得不是很清楚. 本文我们通过一个最简单的例子来学习. 用如下命令行创建一个基于nginx的deployment ...

  5. 一篇文章让你理解Ceph的三种存储接口(块设备、文件系统、对象存储)

    “Ceph是一个开源的.统一的.分布式的存储系统”,这是我们宣传Ceph时常说的一句话,其中“统一”是说Ceph可以一套存储系统同时提供块设备存储.文件系统存储和对象存储三种存储功能.一听这句话,具有 ...

  6. 【Web前端Talk】“用数据说话,从埋点开始”-带你理解前端的三种埋点

    埋点到底是什么呢? 引用自百科的原话是,埋点分析网站分析的一种常用的数据采集方法.因此其本质是分析,但是靠什么分析呢?靠埋点得到的数据.通俗来讲,就是当我想要在某个产品上得到用户的一些行为数据用来分析 ...

  7. 深入理解Java的三种工厂模式

    一.简单工厂模式 简单工厂的定义:提供一个创建对象实例的功能,而无须关心其具体实现.被创建实例的类型可以是接口.抽象类,也可以是具体的类 实现汽车接口 public interface Car { S ...

  8. 浅谈OC对象初始化的三种姿势

    一.普通程序猿普通程序员使用最常见路人姿势等场.普普通通,纯属陆仁辈. 陆仁贾写法: // view 1 UIView *v1 = [UIView alloc] initWithFrame:CGRec ...

  9. 正确开启Mockjs的三种姿势:入门参考(一)

    一.文章初衷 阅读本文章需要注意以下几点: 文章不主要介绍Mockjs的使用语法 文章暂不涉及Mockjs的第三方封装框架 文章会结合以往做过上线项目的方式总结 想主要介绍如何使用Mockjs,是因为 ...

随机推荐

  1. zookeeper集群配置详细教程

      第一步:环境准备 环境 版本 说明 JDK 1.8 zookeeper运行所需 centos 7 操作系统 需要配置好JDK的环境变量 zookeeper-3.4.9.tar.gz 3.4.9 z ...

  2. 40个Java多线程面试问题

    1. 多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡.所谓"知其然知其所以然","会用"只 ...

  3. 腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践

    本文来自腾讯前端开发工程师“ wendygogogo”的技术分享,作者自评:“在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦.” 1.GIF格式的历史 GIF ( Gr ...

  4. 音视频编解码——LAME

    一.LAME简介 LAME是目前非常优秀的一种MP3编码引擎,在业界,转码成Mp3格式的音频文件时,最常用的就是LAME库.当达到320Kbit/s时,LAME编码出来的音频质量几乎可以和CD的音质相 ...

  5. SpringAop实操之记录关键业务请求数据

    AOP,中文名称,切面.在不影响业务代码情况下,实现想要的功能,是个真炫酷的事. aop是个好东西,记录日志是必须的. 记录数据也一样的,那么也是可以用aop来实现的,这里借助注解一起解决问题吧. 因 ...

  6. Spark从入门到精通(一)

    什么是Spark 大数据计算框架 离线批处理 大数据体系架构图(Spark) Spark包含了大数据领域常见的各种计算框架:比如Spark Core用于离线计算,Spark SQL用于交互式查询,Sp ...

  7. 可能是把Java内存区域讲的最清楚的一篇文章

    写在前面(常见面试题) 下面是面试官可能在“Java内存区域”知识点问你的问题,快拿出小本本记下来! 基本问题: 介绍下Java内存区域(运行时数据区). Java对象的创建过程(五步,建议能默写出来 ...

  8. Spring Boot 的 10 个核心模块

    学习 Spring Boot 必须得了解它的核心模块,和 Spring 框架一样,Spring Boot 也是一个庞大的项目,也是由许多核心子模块组成的. 你所需具备的基础 告诉你,Spring Bo ...

  9. Mac OS Eclipse 调试快捷键不好使(失效)的情况

    Eclipse调试使用的F5  F6  F8一直都好用,结果一次调试后忽然不好使. 问题原因,尚未知晓. 解决办法,重启机器.

  10. 深入理解Java Stream流水线

    前面我们已经学会如何使用Stream API,用起来真的很爽,但简洁的方法下面似乎隐藏着无尽的秘密,如此强大的API是如何实现的呢?Pipeline是怎么执行的,每次方法调用都会导致一次迭代吗?自动并 ...