未加星标

ES6 异步编程之二:Promise

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二04 | 时间 2017 | 作者 红领巾 ] 0人收藏点击收藏
异步回调的泥潭

异步回调是最直接的异步结果处理模式,将一个回调函数 callback 扔进异步处理函数中,当异步处理获得结果之后再调用这个回调函数就可以继续之后的处理,但是如果这个 callback 又是一个异步调用呢?众所周知的,在javascript中异步回调的层层嵌套几乎是反人性的,代码编写、修改和阅读对我等有代码洁癖的人而言是一种煎熬,这便是异步回调泥潭了。

今天对于处理异步调用已经有了很多成熟的方案,在我看来这些方案都无外乎在解决一个问题: “如何能看似顺序地传递异步调用的结果?” ,本文要说的 Promise 就是ES6原生提供的一个解决方案。

在对 Promise 进行叙述之前,依旧引用阮大的《ECMAScript 6入门》一书中的 Promise章节 便于大家更严谨和全面的学习和参考。

Promise

承诺,即对未来的许诺,如果诺言实现, 然后 ( then )就如何如何…… Promise 极其生动的讲述了一个 言出必行 的故事。

new Promise(function(resolve, reject){ //开始实现承诺 .... .... if(承诺兑现时) { resolve(dollars); //兑现承诺的结果是得到'一大笔美金' } else { reject('绝交'); //没兑现承诺就绝交 } }).then(function(dollars){ //然后有钱了,买房买车娶妻生子 let d1 = buyHouse(dollars); //把每次消费剩余的钱传给下一个函数 let d2 = buyCar(d1); let d3 = marry(d2); makeBaby(d3); }).catch(function(result){//然后如果绝交了,还是继续吃土 //继续吃土 }); console.log('故事开始....');

看过上面的这个俗不可耐的故事之后需要理解几件事情:

言出必行:一个 Promise 构造出来之后,构造时传入的异步函数就立即执行;*

注:因大凡使用promise都是在异步调用场景,下文所说的异步函数都是指构造promise时传入的函数*

Promise 实例内部维护了一个状态机,状态变化只可能是 pending 到 resolved 或者 pending 到 rejected ;

执行 resolve : pending 变化到 resolved

执行 reject : pending 变化到 rejected

抛出错误: pending 变化到 rejected

then 的第一个回调函数 只会 在发生了 resolve 之后执行,本质上是在 Promise 到达 resolved 状态执行;

then 的第二个回调函数或者 catch 的回调函数会在发生 reject 之后或者异步函数执行抛出错误时执行,本质上是在 promise 到达 rejected 状态时执行;

异步函数执行得到结果可以通过 resolve 或者 reject 将结果传出;

调用 resolve 传入的值会作为 then 第一个回调函数的入参

调用 reject 传入的值作为 then 第二个回调函数或者 catch 的回调函数的入参

如果异步函数抛出了异常,异常会作为 then 第二个回调函数或者 catch 的回调函数的入参

'故事开始....'会先输出,而不是等到 then 的回调函数执行完毕才输出,说明传入 then 的回调函数是异步执行,同理 catch 也是一样;

异步函数调用链

then 和 catch 都是 Promise 的实例方法,都返回一个新的 Promise ,因此可以轻而易举地实现链式编程,比如上面的例子中“把每次消费剩余的钱”传给下一个函数可以改写成这样:

....//前面省略 .then(function(dollars){ return buyHouse(dollars); }).then(function(d1){ return buyCar(d1); }).then(function(d2){ return marry(d2); }).then(function(d3){ return makeBaby(d3); }).catch(function(result){ //继续吃土 });

看到这里你可能认为前一个 then 回调函数的返回值是后一个 then 的回调函数的入参,但这是不准确的,因为当 then 回调函数返回的是个 Promise 对象时,这个 Promise 对象到终态时后一个 then 才会执行,并且该 Promise 对象执行 resolve 时的入参才是后一个 then 的回调函数入参;

此时有必要对 Promise 的一个类方法 resolve 做以下说明,它的特性两句话:

如果传入的是个 Promise 对象,则直接返回这个 Promise ;

如果是其他任何一个值(包括Error对象和undefined)则直接转换为一个 resolved 状态的 Promise 对象;

比如说下面的代码:

//以下的p1和p2逻辑上等同 let p1 = Promise.resolve(1); let p2 = new Promise(function(resolve, reject) { resolve(1); }); //以下的p3和p4等同 let p3 = new Promise(function(r, j) {}); let p4 = Promise.resolve(p3); console.log(p3 == p4); //true console.log(p3 === p4); //true //以下三者逻辑上等同 Promise.resolve().then(function(dollars) { return 1 + 1; }).then(function(v) { console.log(v); }); Promise.resolve().then(function(dollars) { return new Promise(function(r, j) { r(1 + 1) }); }).then(function(v) { console.log(v); }); Promise.resolve().then(function(dollars) { return Promise.resolve(1 + 1); }).then(function(v) { console.log(v); });

我们可以利用 Promise 异步执行结果传出的机制和 then 的链式调用,将层层嵌套的函数调用变为通过 then 顺序连接的链式调用

从写法和形式上看是不是人性很多呢?

通过 Promise 实现的链式异步函数调用,以斐波那契数列举例如下:

//一个异步的斐波那契计算 function fibonacci(v) { return new Promise(function(resolve, reject) { //每一个异步调用都返回了一个Promise setTimeout(function() { console.log(`${v.a}`); [v.a, v.b] = [v.b, v.a + v.b]; resolve(v); }, 500); }); } //以下两者逻辑等同,每个then都等待上一个promise的结果形成一条链。 // fibonacci({ a: 0, b: 1 }) // .then(fibonacci) // .then(fibonacci) // .then(fibonacci) // .then(fibonacci) // .then(fibonacci) // .then(fibonacci); Promise.resolve() .then(() => fibonacci({ a: 0, b: 1 })) .then(fibonacci) .then(fibonacci) .then(fibonacci) .then(fibonacci) .then(fibonacci) .then(fibonacci);

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

主题: JavaScriptECMAScriptJava消费
分页:12
转载请注明
本文标题:ES6 异步编程之二:Promise
本站链接:http://www.codesec.net/view/531830.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(40)