假设我想在单个 JS 模块中导出一些通过调用某个异步函数获得的值。什么机制让导出等待result/Promise被解决?
作为示例代码片段,我把它放在这里
function go() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("Success!"), 3000);
});
}
let AS;
go().then((x) => {
AS = x;
});
module.exports = AS;
此函数可以发出任何 API 请求。 我不想导出整个函数并在其他模块中调用它。
最佳答案
给你两个答案:
使用 CommonJS (CJS)
对于 CommonJS(您在该示例中使用的模块系统),最好的选择是导出 promise 。这样,使用您的模块的代码就有了一种标准方法来处理值可能尚不可用的事实——消费 promise :
require("./your-moudule")
.then(AS => {
// ...use `AS` here...
})
.catch(error => {
// ...handle the fact we didn't get it here...
});
但如果您想改为导出值,则可以,但这通常不是您的最佳方法。您可以通过导出对象然后更新其 AS
属性来实现:
function go() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("Success!"), 500);
});
}
module.exports = {AS: undefined};
go().then((x) => {
module.exports.AS = x;
});
使用您的模块的模块将不得不处理这样一个事实,即一段时间内,它们将变得未定义
。下面是使用上述模块的代码:
const mod = require("./promise");
const timer = setInterval(() => {
const AS = mod.AS;
console.log("AS = " + AS);
if (AS) {
clearInterval(timer);
}
}, 100);
如果你运行它,你会看到 AS = undefined
~5 次,然后是 AS = Success!
。
使用 JavaScript 模块 (ESM)
如果您可以改为使用 JavaScript 模块(Node.js 在 v12 中支持它们在标志后面,而在 v13+ 中没有标志,请将 "type": "module"
放入您的 package.json
),你有第三个选项:top-level await
.使用顶级 await
(在我写这篇文章时正在积极添加到 JavaScript 引擎中),您可以让您的模块执行等待一个 promise 来解决。所以你会这样做:
function go() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("Success!"), 500);
});
}
const AS = await go();
export default AS; // Or `export { AS };`, but your CJS code was effectively doing `export default`
如果需要,您可以组合这些行。对于默认导出
export default await go();
对于命名导出:
export const AS = await go();
使用您的模块的模块不必知道 AS
值来自异步源这一事实;在您的模块评估完成之前(在 promise 解决之后),它们不会被评估。他们只是像往常一样导入:
import AS from "./promise.js"; // If it's the default export
console.log("AS = " + AS);
顶级 await
在 --harmony-top-level-await
标志后面的 Node v13+ 中,很快就会进入浏览器。
关于javascript - NodeJS,JS如何在模块中导出Promise值,而不是函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62607868/