【问题标题】:Why does this await outside async function work?为什么这等待外部异步功能起作用?
【发布时间】:2021-06-02 14:01:32
【问题描述】:

所以我一直在摆弄javascript,发现了一个奇怪的行为,反正现在。

鉴于这些 sn-ps

database.js

import MongoDB from "mongodb";

const MongoClient = MongoDB.MongoClient;

const uri = "mongodb://127.0.0.1:27017/?poolSize=20&writeConcern=majority"

const mongoClient = new MongoClient(uri, { useUnifiedTopology: true });

let instance;
const getInstance = async () => {
    if (!instance) {
        instance = mongoClient.connect();
    }
    return instance;
}

export const client = await getInstance();
services.js

import { client } from "./database"

//return array of items
function getUserRecommendationItems(username) {
    const shopifyDb = client.db('Shopify');
    const product = shopifyDb.collection('product');
    return product.find().toArray();
}

export default { getUserRecommendationItems }
index.js

import services from "./services"

(async () => {
    const products = await services.getUserRecommendationItems();
    console.log(products);
})();

当我删除 database.js 中的 await 时,它会抛出一个错误,因为它需要等待客户端首先连接。

我的问题是,为什么我可以在 service.js 中访问 client 而无需将其放入异步函数中? 这是否意味着导出和导入是底层的异步函数?

【问题讨论】:

  • 据我了解,您已经从 database.js 中导出了已履行的承诺(客户端)。因此,当您在 service.js 中访问客户端时,您正在使用该对象。另外,您在问题中添加 index.js 的原因是什么?描述中没有。
  • @TusharShahi 感谢您的回复,我添加 index.js 只是为了让我的问题完全符合上下文,但仍然留下了主要问题。我试图在 getInstance 函数中移动 await ,但我得到了 client.db is not a function 错误。这又很奇怪,因为mongoClient.connect() 是一个承诺,它应该有效。
  • “我得到 client.db 不是函数错误。这又很奇怪” - 异步函数返回一个承诺 - 当你删除 @987654331 之前的 await @ 函数,您正在导出处于待处理状态的承诺。您需要await 客户端或链接then 方法调用以使用它所实现的值。在待处理的 promise 上调用 db 方法是导致错误的原因。

标签: javascript node.js mongodb asynchronous


【解决方案1】:

您的环境似乎支持the top-level await proposal。该提案目前处于第 4 阶段,这意味着“完成”并且可以正式包含在规范中。但支持可能仍会有所不同。

Quoting the proposal:

顶级await 让我们依靠模块系统本身来处理所有这些承诺,并确保事情得到很好的协调。上面的例子可以简单地编写和使用如下:

// awaiting.mjs
import { process } from "./some-module.mjs";
const dynamic = import(computedModuleSpecifier);
const data = fetch(url);
export const output = process((await dynamic).default, await data);
// usage.mjs
import { output } from "./awaiting.mjs";
export function outputPlusValue(value) { return output + value }

console.log(outputPlusValue(100));
setTimeout(() => console.log(outputPlusValue(100), 1000);

awaiting.mjs 中的awaits 解决了它们的Promise 之前,usage.mjs 中的所有语句都不会执行,因此设计上避免了竞争条件。这是一个扩展,如果awaiting.mjs 没有使用顶级await,则usage.mjs 中的所有语句都不会执行,直到awaiting.mjs 被加载并且其所有语句都已执行。

因为您在database.js 中有一个顶级await,所以services.js 只会在该模块的client 承诺解决后执行。

【讨论】:

猜你喜欢
  • 2013-05-14
  • 2013-03-17
  • 1970-01-01
  • 1970-01-01
  • 2021-10-22
  • 2023-04-04
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
相关资源
最近更新 更多