理解 async/await

2023-01-16 0 512

ES7 明确提出的async 表达式,总算让 JavaScript 对触发器操作形式有了毁灭者软件系统。No more callback hell。

async 表达式是 Generator 表达式的句法糖。采用 关键字 async 来则表示,在表达式外部采用 await 来则表示触发器。

想较于 Generator,Async 表达式的改良是上面五点:内建开伞器。Generator 表达式的继续执行要倚靠开伞器,而 Aysnc 表达式便携式开伞器,初始化形式跟一般表达式的初始化那样更快的句法。async 和 await 相对 * 和 yield 更为句法化更广的精确性。co 组件签订合同,yield 指示前面根本无法是 Thunk 表达式或 Promise第一类。而 async 表达式的 await 指示前面则能是 Promise 或是 原初类别的值(Number,string,boolean,但此时等同同步操作形式)codice是 Promise。async 表达式codice是 Promise 第一类,比 Generator 表达式回到的 Iterator 第一类方便快捷,能间接采用 then() 形式展开初始化

Async 与其它触发器操作形式的对照

先表述两个

function fetchUser() { return new Promise((resolve, reject) => { fetch(https://api.github.com/users/superman66) .then((data) => { resolve(data.json()); }, (error) => { reject(error); }) }); }

Promise 形式

/** * Promise 形式 */ function getUserByPromise() { fetchUser() .then((data) => { console.log(data); }, (error) => { console.log(error); }) } getUserByPromise();

Promise 的形式虽然解决了 callback hell,但是这种形式充满了 Promise的 then() 形式,如果处理流程复杂的话,整段代码将充满 then。句法化不明显,代码流程不能很好的则表示继续执行流程。

Generator 形式
/** * Generator 形式 */ function* fetchUserByGenerator() { const user = yield fetchUser(); return user; } const g = fetchUserByGenerator(); const result = g.next().value; result.then((v) => { console.log(v); }, (error) => { console.log(error); })

Generator 的形式解决了 Promise 的一些问题,流程更为直观、句法化。但是 Generator 的问题是,表达式的继续执行需要倚靠开伞器,每次都需要通过 g.next() 的形式去继续执行。

async 形式
/** * async 方式 */ async function getUserByAsync(){ let user = await fetchUser(); return user; } getUserByAsync() .then(v => console.log(v));

async 表达式完美的解决了上面两种形式的问题。流程清晰,直观、句法明显。操作形式触发器流程就如同操作形式同步流程。同时 async 表达式便携式开伞器,继续执行的时候无需手动加载。

句法

async 表达式回到两个 Promise 第一类

async 表达式外部 return 回到的值。会成为 then 形式回调表达式的参数。

async function f() { return hello world }; f().then( (v) => console.log(v)) // hello world

如果 async 表达式外部抛出异常,则会导致回到的 Promise 第一类状态变为 reject 状态。抛出的错误而会被 catch 形式回调表达式接收到。

async function e(){ throw new Error(error); } e().then(v => console.log(v)) .catch( e => console.log(e));

async 表达式回到的 Promise 第一类,要等到外部所有的 await 指示的 Promise 第一类继续执行完,才会发生状态改变

也就是说,只有当 async 表达式外部的触发器操作形式都继续执行完,才会继续执行 then 形式的回调。

const delay = timeout => new Promise(resolve=> setTimeout(resolve, timeout)); async function f(){ await delay(1000); await delay(2000); await delay(3000); return done; } f().then(v => console.log(v)); // 等待6s后才输出 done

正常情况下,await 指示前面跟着的是 Promise ,如果不是的话,也会被转换成两个 立即 resolve 的 Promise

如上面这个例子:
async function f() { return await 1 }; f().then( (v) => console.log(v)) // 1

如果回到的是 reject 的状态,则会被 catch 形式捕获。

Async 表达式的错误处理

async 表达式的句法不难,难在错误处理上。

先来看上面的例子:
let a; async function f() { await Promise.reject(error); a = await 1; // 这段 await 并没有继续执行} f().then(v => console.log(a));

如上面所示,当 async 表达式中只要两个 await 出现 reject 状态,则前面的 await 都不会被继续执行。

解决办法:能添加 try/catch。
// 正确的写法 let a; async function correct() { try { await Promise.reject(error) } catch (error) { console.log(error); } a = await 1; return a; } correct().then(v => console.log(a)); // 1

如果有多个 await 则能将其都放在 try/catch 中。

如何在项目中采用

依然是通过 babel 来采用。

只需要设置 presets 为 stage-3 即可。

安装依赖:
npm install babel-preset-es2015 babel-preset-stage-3 babel-runtime babel-plugin-transform-runtime

修改.babelrc:

“presets”: [“es2015”, “stage-3”], “plugins”: [“transform-runtime”]

这样就能在项目中采用 async 表达式了。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务