【问题标题】:Why I cannot get value from async await by waiting synchronously?为什么我不能通过同步等待从异步等待中获取价值?
【发布时间】:2016-05-07 19:48:17
【问题描述】:

我正在尝试同步获取 mongodb 实例。我知道不建议这样做,但我只是尝试并想知道为什么这不起作用。 this.db 在等待 10 秒后仍然未定义,而通常异步代码在不到 500 毫秒的时间内获得它。

Repository.js:

var mongodb = require('mongodb');
var config = require('../config/config');

var mongoConfig = config.mongodb;
var mongoClient = mongodb.MongoClient;

class Repository {
    constructor() {
        (async () => {
            this.db = await mongoClient.connect(mongoConfig.host);
        })();
    }

    _getDb(t) {
        t = t || 500;
        if(!this.db && t < 10000) {
            sleep(t);
            t += 500;
            this._getDb(t);
        } else {
            return this.db;
        }
    }

    collection(collectionName) {
        return this._getDb().collection(collectionName);
    }
}

function sleep(ms) {
    console.log('sleeping for ' + ms + ' ms');
    var t = new Date().getTime();
    while (t + ms >= new Date().getTime()) {}
}

module.exports = Repository;

app.js:

require('../babelize');

var Repository = require('../lib/Repository');
var collection = new Repository().collection('products');

【问题讨论】:

  • JS 是单线程的,根据定义,busy-loop 的存在会阻止设置值。如果 JS 一直在循环,它就没有机会分配db。您最好将这个问题改写为“我应该如何重写这段代码才能正常工作”。
  • 我认为问题应该至少部分地在问题的标题中表现出来。 This code 要求读者查看问题的正文。
  • 简而言之,您不能从同步函数返回异步值。你根本无法做到这一点。您繁忙的等待循环不会像 Javascript 那样运行。因为您永远不允许事件循环处理下一个事件,所以您的数据库完成回调将永远不会被调用。您必须为异步结果编程。返回一个承诺或传入一个回调。
  • 可能应该只是阅读这个How do I return a value from an asynchronous function。那里涵盖了所有设计选项。

标签: node.js mongodb async-await babeljs


【解决方案1】:

Javascript 是一种基于事件的架构。所有代码都是通过事件队列中的一个事件启动的,只有在前一个事件的代码完成执行时,才会从事件队列中提取下一个事件。这意味着您的主要 Javascript 代码是单线程的。

因此,当您触发异步操作时,它会启动一个操作,当该操作完成时,它会将一个事件放入事件队列中。该事件(将触发异步操作的回调)在前一个事件的代码完成运行并返回系统之前不会运行。

那么,现在开始您的代码。您开始运行一些启动异步操作的代码。然后,您将永远循环并且永远不会返回系统。因此,异步操作完成后事件队列中的下一个事件将永远无法运行。

因此,简而言之,您不能在等待异步操作完成的循环中旋转。这与 Javascript 使用的事件驱动方案不兼容。您永远不会返回事件系统来让异步完成回调运行。所以,你只是有一个死锁或无限循环。

相反,您需要通过返回承诺或传入稍后调用的回调来编写异步响应代码。并且您的代码需要完成执行,然后让回调在将来的某个时间被调用。 Javascript 中没有旋转循环等待其他东西运行。

您可以在此处查看异步编码选项:How do I return the response from an asynchronous call?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-06
    • 2016-07-07
    • 2016-03-25
    • 2017-10-09
    • 2020-03-13
    • 1970-01-01
    相关资源
    最近更新 更多