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 相关文章推荐
阻止JavaScript事件冒泡传递(cancelBubble 、stopPropagation)
May 08 Javascript
js立即执行函数: (function ( ){})( ) 与 (function ( ){}( )) 有什么区别?
Nov 18 Javascript
Javascript同时声明一连串(多个)变量的方法
Jan 23 Javascript
jquery easyui DataGrid简单示例
Jan 23 Javascript
jquery实现自定义图片裁剪功能【推荐】
Mar 08 Javascript
React+react-dropzone+node.js实现图片上传的示例代码
Aug 23 Javascript
微信小程序实现点击按钮移动view标签的位置功能示例【附demo源码下载】
Dec 06 Javascript
layDate插件设置开始和结束时间
Nov 15 Javascript
用Cordova打包Vue项目的方法步骤
Feb 02 Javascript
浅谈JavaScript中你可能不知道URL构造函数的属性
Jul 13 Javascript
微信小程序实现天气预报功能(附源码)
Dec 10 Javascript
关于JavaScript回调函数的深入理解
Jun 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
PHP常用的文件操作函数经典收藏
2013/04/02 PHP
php四种基础算法代码实例
2013/10/29 PHP
ThinkPHP之用户注册登录留言完整实例
2014/07/22 PHP
Laravel框架基于ajax和layer.js实现无刷新删除功能示例
2019/01/17 PHP
JavaScript 类的定义和引用 JavaScript高级培训 自定义对象
2010/04/27 Javascript
20行代码实现的一个CSS覆盖率测试脚本
2013/07/07 Javascript
javaScript 计算两个日期的天数相差(示例代码)
2013/12/27 Javascript
js中哈希表的几种用法总结
2014/01/28 Javascript
基于Angularjs实现分页功能
2016/05/30 Javascript
vue数据双向绑定原理解析(get & set)
2017/03/08 Javascript
nodejs多版本管理总结
2018/04/03 NodeJs
详解vue中this.$emit()的返回值是什么
2019/04/07 Javascript
详解vue父子组件关于模态框状态的绑定方案
2019/06/05 Javascript
javascript 构建模块化开发过程解析
2019/09/11 Javascript
[51:30]OG vs LGD 2018国际邀请赛淘汰赛BO3 第二场 8.26
2018/08/30 DOTA
复习Python中的字符串知识点
2015/04/14 Python
Python查找函数f(x)=0根的解决方法
2015/05/07 Python
Flask框架URL管理操作示例【基于@app.route】
2018/07/23 Python
Linux下Python安装完成后使用pip命令的详细教程
2018/11/22 Python
Python高级特性之闭包与装饰器实例详解
2019/11/19 Python
python numpy 反转 reverse示例
2019/12/04 Python
pygame实现飞机大战
2020/03/11 Python
Python之Django自动实现html代码(下拉框,数据选择)
2020/03/13 Python
Pycharm配置PyQt5环境的教程
2020/04/02 Python
通过python 执行 nohup 不生效的解决
2020/04/16 Python
Python之Matplotlib文字与注释的使用方法
2020/06/18 Python
Python如何实现自带HTTP文件传输服务
2020/07/08 Python
毕业生个人投资创业计划书
2014/01/04 职场文书
关于廉洁的广播稿
2014/01/30 职场文书
高一学生期末评语
2014/04/25 职场文书
尊师重教演讲稿
2014/09/04 职场文书
高中毕业典礼演讲稿
2014/09/09 职场文书
2014年管理工作总结
2014/11/22 职场文书
无线电知识基础入门篇
2022/02/18 无线电
python的列表生成式,生成器和generator对象你了解吗
2022/03/16 Python
Python采集壁纸并实现炫轮播
2022/04/30 Python