如何使请求同步以等待相同NodeJS / express Web服务的另一个请求?

时间:2019-01-21 17:44:10

标签: node.js express request wait synchronous

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

首先从浏览器调用请求1:/call,并且必须等待,例如,从另一个浏览器调用请求2:/trigger,然后请求1必须返回其结果。 / p>

这是我的示例代码,非常简单,但是“ TODO”部分非常困难。我已经尝试过使用while循环,但是它会阻塞整个过程,并且不接受请求2(我认为可以通过promise或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
    });
});

2 个答案:

答案 0 :(得分:1)

可能最容易使用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

答案 1 :(得分:0)

可以使用事件来实现:

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