我们都知道在异步编程中, await 只能在 aysnc function 里进行使用。await 提升了异步编程的体验,使我们能像同步函数那样处理异步函数。同时我们也会好奇 await 只能在 aysnc 中使用
ECMAScript 提案 Top-level await
允许开发者在 async 函数外使用 await 字段,目前已进入 tc39 Stage 3。
Top-level await 允许你将整个 JS 模块视为一个巨大的 async 函数,这样就可以直接在顶层使用 await,而不必用 async 函数包一层。
1. 在引入top-level await之前
// ------ method.js
export function double(num) {
return num * 2;
}
export function square(num) {
return num * num;
}
// ------ middleware.js
import { double, square } from "./method.js";
let doubleOutput;
let squareOutput;
// IIFE
(async () => {
await requestData();
doubleOutput = double(10);
squareOutput = square(10);
})();
// 模拟接口请求
function requestData(delays = 1000) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(console.log("❤️"));
}, delays);
});
}
export { doubleOutput, squareOutput };
// ------ index.js
import { doubleOutput, squareOutput } from "./middleware.js";
console.log("doubleOutput-init", doubleOutput); // undefined
console.log("squareOutput-init", squareOutput); // undefined
setTimeout(() => console.log("doubleOutput-delay", doubleOutput), 2000); // 20
setTimeout(() => console.log("squareOutput-delay", squareOutput), 2000); // 100
### 2.使用 Export Promise 来代替初始化
// ------ method.js
export function double(num) {
return num * 2;
}
export function square(num) {
return num * num;
}
// ------ middleware.js
import { double, square } from "./method.js";
let doubleOutput;
let squareOutput;
// IIFE
export default (async () => {
await requestData();
doubleOutput = double(10);
squareOutput = square(10);
return { doubleOutput, squareOutput };
})();
// 模拟接口请求
function requestData(delays = 1000) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(console.log("❤️"));
}, delays);
});
}
export { doubleOutput, squareOutput };
// ------ index.js
import promise from "./middleware.js";
promise.then(({ doubleOutput, squareOutput }) => {
console.log("doubleOutput-delay", doubleOutput); // 20
console.log("squareOutput-delay", squareOutput); // 100
});
所有引用都要写成 promise 结构,十分不方便
3. 使用top-level await
// ------ method.js
export function double(num) {
return num * 2;
}
export function square(num) {
return num * num;
}
// ------ middleware.js
import { double, square } from "./method.js";
let doubleOutput;
let squareOutput;
// "plugins": ["@babel/plugin-syntax-top-level-await"]
await requestData();
doubleOutput = double(10);
squareOutput = square(10);
// 模拟接口请求
function requestData(delays = 1000) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(console.log("❤️"));
}, delays);
});
}
export { doubleOutput, squareOutput };
// ------ index.js
import { doubleOutput, squareOutput } from "./middleware.js";
console.log("doubleOutput-init", doubleOutput); // 20
console.log("squareOutput-init", squareOutput); // 100
4. 过去
当 async/await
首次引用时,尝试在 async
函数外部使用 await
的结果是产生 SyntaxError
。大多数开发者使用立即执行异步函数表达式的方式来使用该功能。
await Promise.resolve(console.log('?'));
// → SyntaxError: await is only valid in async function
(async function () {
await Promise.resolve(console.log('?'));
// → ?
})();
5. 现在
在 top-level await 的支持下,下面代码可以替换模块中常见代码
await Promise.resolve(console.log('?'));
// → ?
6. 何时使用
参考 spec proposal repository
6.1 动态依赖导入
const strings = await import(`/i18n/${navigator.language}`);
这允许在模块的运行时环境中确认依赖项。
6.2 资源初始化
const connection = await dbConnector();
允许模块申请资源,同时也可以在模块不能使用时抛出错误。
6.3 依赖回退
let jQuery;
try {
jQuery = await import('https://cdn-a.example.com/jQuery');
} catch {
jQuery = await import('https://cdn-b.example.com/jQuery');
}
希望从 CDN A 加载 JavaScript 库,如果它加载失败,将加载 CDN B
结尾
top-level await 在某些特定场景有很方便的作用,但是目前这个一特性还没有很好的运用到生产代码中
相关资源:
-
@babel/plugin-syntax-top-level-await
-
github.com/tc39/propos…
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!