在NodeJS中忙于等待

时间:2020-09-22 03:30:48

标签: javascript node.js

有两个异步功能。一个将设置一个变量,另一个将等待变量的更改,如下面的代码所示。即使通常的做法是使用 事件或承诺,在我的情况下这是不可行的。

    "delivery-status": {
        "tls": true,
        "mx-host": "gmail-smtp-in.l.google.com",
        "attempt-no": 1,
        "description": "",
        "session-seconds": 0.44887804985046387,
        "utf8": true,
        "code": 550,
        "message": "5.7.1 [209.61.151.231      14] Messages missing a valid address in From:\n5.7.1 header, or having no From: header, are not accepted. e10si1791456oth.257 - gsmtp",
        "certificate-verified": true
    },
    "recipient-domain": "gmail.com",
    "event": "failed",
    "campaigns": [],
    "reason": "generic",
    "user-variables": {},
    "flags": {
        "is-routed": false,
        "is-authenticated": true,
        "is-system-test": false,
        "is-test-mode": false
    },
    "log-level": "error",

我不知道为什么function delay(ms: number): Promise<void> { return new Promise(resolve => { setTimeout(() => { resolve(); }, ms); }); } function async fn1() { let done = false; (async () => { await delay(100); // simulate some work done = true; })(); await (async () => { while (!done) { } // do other things })(); } function async fn2() { let done = false; (async () => { await delay(100); // simulate some work done = true; })(); await (async () => { while (!done) { await delay(200); // introduce some extra delay } // do other things })(); } 会停留在fn1循环中而while会起作用。 因为它们之间的唯一区别是后者 引入了一些额外的等待。这与一些潜在的 JS / V8解释器的线程调度机制?

我正在使用Node 12.18.3和TypeScript 4.0.3。

编辑:修正fn2的定义。

2 个答案:

答案 0 :(得分:1)

JavaScript是单线程的‡。因此,任何形式的繁忙等待都会导致线程完全阻塞,从而阻止其进入事件循环,这意味着不会处理任何事件。

在C级别,解释器非常简单。由于它是单线程的,因此不需要任何复杂的逻辑,只需一个无限的while循环。在伪代码中,它是这样的:

do {

    event_queue = execute_javascript()

    completed_events = wait_for_events()

    for_each (event from completed_events) {

        this_event = event_queue.find_one_matching(event)

        execute_javascript(this_event.callback)
    }

} while (there_is_pending_events)

如您所见,解释器中没有任何内容并行运行。它们都按顺序运行。异步代码等待并行执行,但不并行执行。

在您的代码中,while(){}循环被卡在execute_javascript()中,直到while循环完成,该循环才返回。这意味着解释器被卡住了。

await循环中添加while(){}会使execute_javascript()在等待中返回(并将在await之后的行中再次继续),从而允许解释器继续等待wait_for_events()上的事件。

•注意:有人会告诉您javascript使用后台线程来处理异步代码。他们错了。 Node.js(不是浏览器)确实使用一个,单个附加线程处理磁盘I / O,但仅处理磁盘I / O。网络I / O是在主线程中完成的,如上所述。磁盘I / O之所以这样,是因为Windows,Linux和BSD(BSD包括Mac OSX)之间对异步磁盘I / O API的兼容性很小。

如果您对事件循环和异步代码执行在javascript中的工作原理的底层解释感兴趣,那么您可能会对我对这些其他相关问题的回答感兴趣。在某些情况下,我将向下解释硬件的处理方式。在某些文章中,我探索了如何在C / C ++中完成它:

Is my understanding of asynchronous operations correct?

Is there any other way to implement a "listening" function without an infinite while loop?

node js - what happens to incoming events during callback excution

I know that callback function runs asynchronously, but why?

答案 1 :(得分:0)

对于第一个功能fn1,您将async放在功能之前,但对于fn2,您没有。尝试从第一个功能中删除该功能,看看它是否仍然卡住。

相关问题