NodeJS,JS如何在模块而不是函数中导出Promise值? [英] NodeJS, JS how to export Promise value in a module, not the function?

查看:132
本文介绍了NodeJS,JS如何在模块而不是函数中导出Promise值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我要在单个JS模块中导出一些值,该值是通过调用一些异步函数获得的.使导出等待结果/承诺得到解决的机制是什么?

Let's say I want to export in a single JS module some value which is obtained by calling some async function. What is the mechanism to make the export wait for the result/Promise to be resolved?

作为示例代码片段,我将其放在此处

As an example code snippet I put this here

function go() {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve("Success!"), 3000);
  });
}

let AS;
go().then((x) => {
  AS = x;
});
module.exports = AS;

此函数可以发出任何API请求. 我不想导出整个函数并在其他模块中调用它.

This function could make any API request. I don't want to export the entire function and call it in other module.

推荐答案

为您提供两个答案:

使用CommonJS(在该示例中使用的模块系统),最好的选择是导出promise.这样,使用模块的代码可以通过标准方式来处理该值可能尚不可用的事实-消耗诺言:

With CommonJS (the module system you're using in that example), your best bet is to export the promise. That way, code using your module has a standard way to handle the fact that the value may not be available yet — Consuming the promise:

require("./your-moudule")
.then(AS => {
    // ...use `AS` here...
})
.catch(error => {
    // ...handle the fact we didn't get it here...
});

但是,如果您想导出值,则可以,但这通常不是您的最佳方法.您可以通过导出对象然后更新其AS属性来实现:

But if you want to export the value instead, you can, it's just usually not your best approach. You'd do that by exporting an object and then updating its AS property:

function go() {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve("Success!"), 500);
  });
}

module.exports = {AS: undefined};
go().then((x) => {
  module.exports.AS = x;
});

使用您的模块的模块必须处理这样的事实,即一段时间后,它们将变为undefined.这是使用上述模块的代码:

Modules using your module would have to deal with the fact that for a time, they'll be getting undefined. Here's code using the module above:

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!.

If you run that, you'll see AS = undefined ~5 times and then AS = Success!.

如果您可以改用JavaScript模块(Node.js在v12中将其支持在标记后面,而在v13 +中则没有标记,则将"type": "module"放在package.json中),您将有第三个选择:顶级await .使用顶级await(在我撰写本文时,它会自动添加到JavaScript引擎中),您可以让模块执行等待承诺达成.因此,您可以这样做:

If you can switch to using JavaScript modules instead (Node.js supports them behind a flag in v12 and without a flag in v13+, put "type": "module" in your package.json), you have a third option coming: top-level await. With top-level await (actively being added to JavaScript engines as I write this), you can make your module execution wait for a promise to settle. So you'd do this:

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`

如果需要,可以合并这些行.默认导出

You can combine those lines if you want. For a default export

export default await go();

对于命名导出:

export const AS = await go();

使用您的模块的模块不必知道AS值来自异步源的事实.在您的模块评估完成之前(承诺完成后),才会对它们进行评估.它们只是照常导入:

Modules using your module don't have to be aware of the fact that the AS value comes from an asynchronous source; they aren't evaluated until your module evaluation has finished (after the promise settles). They just import as usual:

import AS from "./promise.js"; // If it's the default export
console.log("AS = " + AS);

顶级await位于标志后面的Node v13 +中,不久将进入浏览器.

Top-level await is in Node v13+ behind the --harmony-top-level-await flag, and will shortly be making its way into browsers.

这篇关于NodeJS,JS如何在模块而不是函数中导出Promise值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆