彻底搞清 JavaScript Promise
基本用法
我们知道,一个 js Promise
对象,我们可以用 then()
、catch()
、finally()
进行链式操作,如:
1 | promiseObj.then((res) => { |
这是 js Promise
的基本使用,但是要用好 Promise
,还有一下几个问题需要搞清楚。
怎样创建 Promise
对象
用 Promise
对象创建 Promise
实例
1 | // 创建 Promise 对象 |
用 async
创建 Promise
实例
async
函数返回一个 Promise
实例,我们可以用来创建 Promise
实例。
1 | async function prm () { |
链式调用时参数是怎样传递的
then() 参数的传递
1 | // 创建 Promise 对象 |
执行上面的代码,我们发现,第1个 then()
的参数是 resolve()
的参数值,第2个 then()
及之后的 then()
的参数值都是其上一个 then()
的返回值。
catch() 参数的传递
catch()
参数的传递和 then()
不同,要把错误从 catch()
传给下一个 catch()
,需要在 catch()
中抛出错误。
1 | Promise.resolve().then(() => { |
在 then() 中怎样传值给上级代码块
js Promise
是异步的,同一个 Promise
的 then()
方法是按代码顺序的一个 then
到下一个 than
的执行,但和than 外部的代码块是异步的。如果要把 then
代码块的值传给上层的代码块,回调是常用的方法,但如果上层代码块还需要返回异代码块中的值的时候,回调就做不到了。
ES2017
标准引入了 async
函数,使得异步操作变得更加方便。
async
函数返回一个 Promise
对象,可以使用 then
方法添加回调函数。当函数执行的时候,一旦遇到 await
就会先等待,等到该处的异步操作完成,再接着执行函数体内后面的语句。加上 await
后,将返回回调函数的返回值。
1 | const prm = new Promise((resolve, reject) => { |
注意
1、await
命令后面的 Promise
对象,运行结果可能是 rejected
,所以最好把 await
命令放在 try...catch
代码块中。
1 | async function myFunction() { |
2、多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。
1 | let foo = await getFoo(); |
上面代码中,getFoo
和 getBar
是两个独立的异步操作(即互不依赖),被写成继发关系。这样比较耗时,因为只有 getFoo
完成以后,才会执行 getBar
,完全可以让它们同时触发。
1 | let [foo, bar] = await Promise.all([getFoo(), getBar()]); |
3、await
命令只能用在 async
函数之中,如果用在普通函数,就会报错。从 ES2022
开始允许 await
可以在顶层使用,不需要在 async
函数中。
参考: ECMAScript 6 入门
彻底搞清 JavaScript Promise
https://coderpan.com/front-end/javascript-promise-get-over.html