JS中Promise函数then的奥秘探究


Posted in Javascript onJuly 30, 2018

Promise概述

Promise对象是CommonJS工作组提出的一种规范,目的是为异步操作提供统一接口。

那么,什么是Promises?

首先,它是一个对象,也就是说与其他JavaScript对象的用法,没有什么两样;其次,它起到代理作用(proxy),充当异步操作与回调函数之间的中介。它使得异步操作具备同步操作的接口,使得程序具备正常的同步运行的流程,回调函数不必再一层层嵌套。

简单说,它的思想是,每一个异步任务立刻返回一个Promise对象,由于是立刻返回,所以可以采用同步操作的流程。这个Promises对象有一个then方法,允许指定回调函数,在异步任务完成后调用。

Promise的then方法可以接受前一个函数的执行结果,还可以保证另一个Promise的顺序执行,这到底是怎么做到的呢?

原理图(先上图)

JS中Promise函数then的奥秘探究

问题需求

如何保证多个 promise 顺序执行?

实例:

var f1 = function (){
 return new Promise(function (resolve, reject){
  setTimeout(function (){
   console.log("f1 ok!")
   resolve("f1 ok!");
  }, 1000)
 });
}
var f2 = function (){
 return new Promise(function (resolve, reject){
  setTimeout(function (){
   console.log("f2 ok!")
   resolve("f2 ok!");
  }, 3000)
 });
}
var f3 = function (){
 return new Promise(function (resolve, reject){
  setTimeout(function (){
   console.log("f3 ok!")
   resolve("f3 ok!");
  }, 2000)
 });
}

当然如果要并行的话,我们很容易想到 Promise.all 方法:

Promise.all([f1(), f2(), f3()]).then(function (data){
 console.log(data)
})
// f1 ok! 
// f3 ok! 
// f2 ok! 
// ["f1 ok!", "f2 ok!", "f3 ok!"]

如果要顺序执行:

f1().then(f2).then(f3)
// f1 ok!
// f2 ok!
// f3 ok!

//或者这样

function f(all) {
 var promise = Promise.resolve();
 all.forEach((p, index) => {
  promise = promise.then(p)
 })
}
f([f1, f2, f3])

那么问题来了,then是如何做到顺序执行的呢,参数既可以是一个普通函数,也可是是一个返回promise的函数?

then的奥秘

很多实现promise的库都比较复杂,如果自己实现的话,可以借鉴下面简单的代码:

Promise.prototype.then = function(onFulfilled, onRejected) {
 var promise = this;
 return new Promise(function(resolve, reject) {
  function handle(value) {
   var ret = typeof onFulfilled === 'function' && onFulfilled(value) || value;
   if (ret && typeof ret['then'] == 'function') {
    ret.then(function(value) {
     resolve(value);
    }, function(reason) {
     reject(reason);
    });
   } else {
    resolve(ret);
   }
  }
  function errback(reason) {
   reason = typeof onRejected === 'function' && onRejected(reason) || reason;
   reject(reason);
  }
  if (promise._status === 'PENDING') {
   promise._resolves.push(handle);
   promise._rejects.push(errback);
  } else if (promise._status === FULFILLED) { 
   callback(promise._value);
  } else if (promise._status === REJECTED) {
   errback(promise._reason);
  }
 });
}

重点在then的实现,看上述代码,每个then返回的是什么,是一个新的 Promise,一个新的 Promise,一个新的 Promise
第二个重点是,在内部又处理了一个 回调函数运行结果是 一个 promise的 判断,如果是那么等待这个promise运行结束才调用 resolve 更改状态,关键是resolve的调用时机,resolve的调用时机,才能够往下执行,这两步就是then函数的关键。
是不是 有点晕,请看最开始的图。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
flexigrid 类似ext grid的JS表格代码
Jul 17 Javascript
如何动态的导入js文件具体该怎么实现
Jan 14 Javascript
jQuery中使用data()方法读取HTML5自定义属性data-*实例
Apr 11 Javascript
jQuery实现有动画淡出效果的二级折叠菜单代码
Oct 17 Javascript
jQuery提示插件qTip2用法分析(支持ajax及多种样式)
Jun 08 Javascript
Active控件问题小结(附解决办法)
Jun 09 Javascript
15款最好的Bootstrap在线编辑器
Aug 03 Javascript
JavaScript函数节流的两种写法
Apr 07 Javascript
vue如何使用 Slot 分发内容实例详解
Sep 05 Javascript
layui实现动态和静态分页
Apr 28 Javascript
什么时候不能在 Node.js 中使用 Lock Files
Jun 24 Javascript
Node.js API详解之 tty功能与用法实例分析
Apr 27 Javascript
浅析java线程中断的办法
Jul 29 #Javascript
还不懂递归?读完这篇文章保证你会懂
Jul 29 #Javascript
如何在js代码中消灭for循环实例详解
Jul 29 #Javascript
Vue-cli3项目配置Vue.config.js实战记录
Jul 29 #Javascript
vue权限路由实现的方法示例总结
Jul 29 #Javascript
JS高级技巧(简洁版)
Jul 29 #Javascript
js运算符的一些特殊用法
Jul 29 #Javascript
You might like
hessian 在PHP中的使用介绍
2010/12/13 PHP
php的ddos攻击解决方法
2015/01/08 PHP
Laravel 5框架学习之模型、控制器、视图基础流程
2015/04/08 PHP
Symfony查询方法实例小结
2017/06/28 PHP
PHP实现单文件、多个单文件、多文件上传函数的封装示例
2019/09/02 PHP
用javascript操作xml
2006/11/04 Javascript
利用jquery操作select下拉列表框的代码
2010/06/04 Javascript
js 弹出框 替代浏览器的弹出框
2010/10/29 Javascript
Extjs EditorGridPanel中ComboBox列的显示问题
2011/07/04 Javascript
自己做的模拟模态对话框实现代码
2012/05/23 Javascript
JS的replace方法详细介绍
2012/11/09 Javascript
javascript改变position值实现菜单滚动至顶部后固定
2013/01/18 Javascript
javascript:void(0)是什么意思示例介绍
2013/11/17 Javascript
JavaScript中的undefined学习总结
2013/11/30 Javascript
JavaScript中的parse()方法使用简介
2015/06/12 Javascript
Bootstrap每天必学之表格
2015/11/23 Javascript
javascript针对cookie的基本操作实例详解
2015/11/30 Javascript
js和jquery实现监听键盘事件示例代码
2020/06/24 Javascript
jQuery实现横向带缓冲的水平运动效果(附demo源码下载)
2016/01/29 Javascript
JavaScript中三种异步上传文件方式
2016/03/06 Javascript
详解JavaScript设计模式开发中的桥接模式使用
2016/05/18 Javascript
[js高手之路]原型式继承与寄生式继承详解
2017/08/28 Javascript
如何从零开始利用js手写一个Promise库详解
2018/04/19 Javascript
JQuery元素快速查找与操作
2018/04/22 jQuery
vue实现简易计算器功能
2021/01/20 Vue.js
Python使用matplotlib绘制正弦和余弦曲线的方法示例
2018/01/06 Python
tensorflow入门之训练简单的神经网络方法
2018/02/26 Python
Python补齐字符串长度的实例
2018/11/15 Python
python 自动识别并连接串口的实现
2021/01/19 Python
使用CSS3制作饼状旋转载入效果的实例
2015/06/23 HTML / CSS
实现向右循环移位
2014/07/31 面试题
《赶海》教学反思
2014/04/20 职场文书
学院党的群众路线教育实践活动第一阶段情况汇报
2014/10/25 职场文书
上课迟到检讨书范文
2015/05/06 职场文书
趣味运动会标语口号
2015/12/26 职场文书
Nginx安装完成没有生成sbin目录的解决方法
2021/03/31 Servers