简体   繁体   English

为什么我无法通过同步等待从异步等待中获得价值?

[英]Why I cannot get value from async await by waiting synchronously?

I am trying to get mongodb instance synchronously. 我试图同步获取mongodb实例。 I know this is not recommended but I just experiment and wonder why this doesn't work. 我知道不建议这样做,但我只是尝试一下,不知道为什么这行不通。 this.db is still undefined after 10 seconds of waiting when normally asynchronous code gets it in less than 500 milliseconds. 当通常的异步代码在不到500毫秒的时间内等待10秒后, this.db仍未定义。

Repository.js: 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: app.js:

require('../babelize');

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

Javascript is an event-based architecture. Javascript是基于事件的体系结构。 All code is initiated via an event from the event queue and the next event is pulled from the event queue ONLY when the code from the previous event has finished executing. 所有代码都是通过事件队列中的事件启动的,只有下一个事件中的代码执行完毕后,才会从事件队列中提取下一个事件。 This means that your main Javascript code is single threaded. 这意味着您的主要Javascript代码是单线程的。

As such, when you fire an async operation, it starts up an operation and when that operation finishes, it puts an event in the event queue. 这样,当您触发异步操作时,它将启动一个操作,并且当该操作完成时,它将一个事件放入事件队列中。 That event (which will trigger the callback for the async operation) will not run until the code from the previous event finishes running and returns back to the system. 该事件(将触发异步操作的回调)将不会运行,直到前一个事件的代码完成运行并返回系统为止。

So, now to your code. 所以,现在到您的代码。 You start running some code which launches an async operation. 您开始运行一些启动异步操作的代码。 Then, you loop forever and never return back to the system. 然后,您将永远循环,再也不会返回系统。 Because of that, the next event in the event queue from the completion of your async operation can NEVER run. 因此,异步操作完成后事件队列中的下一个事件将永远无法运行。

So, in a nutshell, you cannot spin in a loop waiting for an async operation to complete. 因此,简而言之,您无法在循环中旋转以等待异步操作完成。 That's incompatible with the event driven scheme that Javascript uses. 这与Javascript使用的事件驱动方案不兼容。 You never return back to the event system to let the async completion callback ever run. 您再也不会回到事件系统来运行异步完成回调。 So, you just have a deadlock or infinite loop. 因此,您只有一个死锁或无限循环。

Instead, you need to code for an async response by returning a promise or by passing in a callback that is called sometime later. 取而代之的是,您需要通过返回一个Promise或传入一个稍后调用的回调来为异步响应编写代码。 And your code needs to finish executing and then let the callback get called sometime in the future. 而且您的代码需要完成执行,然后在将来的某个时候让回调函数被调用。 No spinning in loops in Javascript waiting for something else to run. Javascript中没有循环等待其他东西运行。

You can see the async coding options here: How do I return the response from an asynchronous call? 您可以在此处看到异步编码选项: 如何返回异步调用的响应?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM