NodeJ中的多个客户端请求

时间:2020-04-01 23:38:30

标签: node.js promise

如果我打/ route2,我会在15s后得到响应,但是在这段时间内/ route1会立即给出响应。 服务器不应等待15秒,然后将响应发送到/ route1。

我读了https://medium.com/@cinish/nodejs-multiple-client-requests-694d6353218b,但听不懂。

我理解的是/ route2,是在控制台P1上,然后是setTimeout(),将其放入外部线程,然后将控制台P2然后是setTimeout(),将其放入外部线程。现在等待setTimeouts()到完成。

(此时,事件循环在等待p1和p2履行时必须处于繁忙状态,因此它不应接受任何新的客户端请求)。 但是确实如此。为什么?

app.get("/route1", (req, res) => {
    res.send("Route1");
});


app.get("/route2", async (req, res) => {

    const p1 = new Promise((resolve, reject) => {
        console.log("P1");
        setTimeout(() => {
            console.log(5);
            resolve();
        }, 15000);
    })
    const p2 = new Promise((resolve, reject) => {
        console.log("P2")
        setTimeout(() => {
            console.log(1);
            resolve();
        }, 1000);
    });

    const ans = await Promise.all([p1, p2]);
    res.send("Route2");
})

1 个答案:

答案 0 :(得分:1)

setTimeout()是“非阻止”。这意味着它将设置计时器,立即从setTimeout()返回,然后继续执行其余代码。

因此,在您的情况下,/route2创建了两个承诺,设置了两个计时器,然后等待Promise.all()完成。在到达await的那一刻,您的async路由处理程序将返回一个promise,并将控制权返回到事件循环。

因此,/route1请求一到,就可以对其进行处理。 /route2在两个计时器都完成后才处于活动状态。

然后,当准备启动更长的计时器时,下一次JS解释器返回事件循环以检查其他事情时,它将看到计时器,正在处理计时器回调并且计时器回调将解决p1承诺,然后使Promise.all()得到解决。

如果我打/ route2,我会在15s后得到响应,但是在这段时间内/ route1会立即给出响应。服务器不应等待15秒,然后将响应发送给/ route1。

如关于setTimeout()的说明是非阻塞的,因此在/route2处理程序等待两个计时器触发时,nodejs可以自由处理其他事件(例如传入的/route1事件)。

我理解的是/ route2,是在控制台P1上,然后是setTimeout(),将其放入外部线程,然后将控制台P2然后是setTimeout(),将其放入外部线程。现在等待setTimeouts()到完成。

计时器不在外部线程中运行。它们是nodejs事件循环中的某种独特设计。计时器按到期时间的顺序存储在排序的链表中。每次JS解释器返回事件循环并到达事件循环的计时器部分时,它仅检查链接列表中最前面的计时器,以查看其时间是否到了。如果是这样,它将触发该事件。如果没有,它将继续寻找其他类型的事件。

最终,如果事件循环不执行任何操作而进入睡眠状态,它将在适当的时间睡眠,以便在计划的下一个计时器运行之前及时唤醒(如果在此之前没有其他唤醒方式)。

(此时,事件循环在等待p1和p2填充时必须处于繁忙状态,因此它不应接受任何新的客户端请求)。但这是为什么?

这是您的主要错误假设。此时,事件循环完全可以自由处理其他事件。设置了这两个计时器,事件循环将在其时间到期时运行其回调,但是在此之前,事件循环将处理任何其他传入事件,例如/route1请求。