如何使请求同步等待同一 NodeJS/express 网络服务的另一个请求?

How to make a request sync wait for another request of the same NodeJS/express webservice?

我已经简化了我的代码,我正在寻找一种方法来正确等待内部 var 增加(如互斥锁)。

请求 #1:/call 首先从浏览器调用,必须等待,请求 #2:/trigger 例如从另一个浏览器调用,然后请求 #1 必须 return它的结果。

这是我的示例代码,很简单,但是"TODO"部分很难。我已经尝试过使用 while 循环,但它阻止了整个过程并且不接受请求 #2(我认为它可以用 promises 或 async/await 来完成,但我不知道如何使用这些)

[code was removed, cf. below]

感谢提前!

编辑: 非常感谢你,grappeq!这是我根据发布和订阅模式的工作代码,并进行了更新,因此 /trigger/call 可以无论顺序是什么都可以启动:

var app = require('express')();
var token = 0;
require("http").createServer(app).listen(8080, () => {
    console.log("Launched");
});
class Quartz {
    constructor() {
        this.callbacks = [];
    }
    retry() {
        throw "";
    }
    call(callback) {
        this.callbacks.push(callback);
        this.trigger();
    }
    trigger(...args) {
        var failedCallbacks = [];
        while (this.callbacks.length > 0) {
            var callback = this.callbacks.shift();
            try {
                callback(...args);
            } catch (e) {
                failedCallbacks.push(callback);
            }
        }
        this.callbacks = failedCallbacks;
    }
};
var quartz = new Quartz();
app.get('/call', (request, response) => {
    console.log("Wait");
    var start = Date.now();
    quartz.call(() => {
        if (token <= 0)
            quartz.retry();
        token--;
        response.status(200).json({
            "func": "/call",
            "value": token,
            "time": Date.now()-start
        });
    });
});
app.get('/trigger', (request, response) => {
    console.log("Trigger");
    var start = Date.now();
    token++;
    quartz.trigger();
    response.status(200).json({
        "func": "/trigger",
        "value": token,
        "time": Date.now()-start
    });
});

可以使用事件实现:

var events = require('events');
var eventEmitter = new events.EventEmitter();

var app = require('express')();

app.listen(8080, () => {
    console.log("Launched");
});

app.get('/call', (req, res) => {
    console.log("Call");

    var start = Date.now();

    eventEmitter.on('tokenEvent', (token) => {
        res.status(200).json({
            "func": "/call",
            "value": token,
            "time": Date.now() - start
        });
    });

});


app.get("/trigger", (req, res) => {
    console.log("Trigger");
    var start = Date.now();

    var token = 1;

    eventEmitter.emit('tokenEvent', token);

    res.status(200).json({
        "func": "/trigger",
        "value": token,
        "time": Date.now() - start
    });

});

请注意,您可能需要保护线路:

eventEmitter.on('tokenEvent', (token) => {
        res.status(200).json({

因为/trigger可以在/call之前调用(可能会用到!res.headersSent

可能最容易使用 publish/subscribe 模式,例如:

var app = require('express')();
var token = 0;
require("http").createServer(app).listen(8080, () => {
    console.log("Launched");
});

class PubSub {
    constructor() {
        this.callbacks = [];
    }

    sub(callback) {
        this.callbacks.push(callback);
    }

    pub(...args) {
        this.callbacks.forEach(callback => { callback(...args); });
    }
};

var pubsub = new PubSub();

app.get('/call', (request, response) => {
    console.log("Call");
    var start = Date.now();
    pubsub.sub(() => {
        response.status(200).json({
            "func": "/call",
            "value": token,
            "time": Date.now()-start
        });
    })
});
app.get('/trigger', (request, response) => {
    console.log("Trigger");
    var start = Date.now();
    pubsub.pub();
    response.status(200).json({
        "func": "/trigger",
        "value": token,
        "time": Date.now()-start
    });
});

当然,使用像 RxJs 这样的库比我在几分钟内拼凑的一些随机代码更受欢迎。

顺便说一句,考虑改用 websockets