【问题标题】:Node.js Express API: How to handle multiple callbacksNode.js Express API:如何处理多个回调
【发布时间】:2018-09-22 11:20:48
【问题描述】:

我有一个 API 端点,它执行一个函数,该函数又通过 Web 套接字监听一些事件,然后通过回调将它的响应返回给 api 端点,因此端点可以用这个对象响应http 请求。

有时我只收到一个事件,有时我从侦听器收到两个事件。当只出现第一个事件时,我没有问题。因为第二个事件有优先级,所以我使用setTimeout 等待它,以防它仍然出现。

问题在于,当第二个事件出现时,我的 API 端点用它的对象进行响应,但之后它崩溃了。我想它与第二个回调有关,我不知道如何处理它。这就是代码的结构:

app.get('/api/myendpoint', function(req, res) {

    myVar_1 = req.query.myvar1;
    myVar_2 = req.query.myvar2;

    myFunction(myVar_1, myVar_2, function(data, error) {
        if (!error) res.json(data);
        else res.json({"error": String(error)});        
    });

});


function myFunction(myVar_1, myVar_2, callback){

    listenOnSocket.someEvent(myVar_1,
        function(error, event) {
            if (error) callback(null, error);
            else setTimeout(function() {callback(event, null);}, 6000);
        }
    );    

    listenOnSocket.someEvent(myVar_2,
        function(error, event) {
            if (!error) callback(event, null); 
            else callback(null, error);
        }
    );

};

这是我的错误的样子:

错误 [ERR_HTTP_HEADERS_SENT]:发送后无法设置标头 给客户

【问题讨论】:

  • 我注意到 myFunction 接受两个参数,但在请求处理程序中调用了三个参数,并且 myFunction 的主体调用了函数中未定义的回调。跨度>
  • 已更新代码@QuiltyKim
  • 我认为首先发生的是1st 事件,您设置了超时以在一段时间后调用回调函数。然后2nd 事件发生,它执行回调并发送标头。然后,当超时完成并执行第一个函数的回调时,您将再次发送响应。

标签: node.js api express callback http-headers


【解决方案1】:

为什么会这样?

  1. 1st 事件发生时,您设置 timeout for 6000 ms 以调用回调函数。
  2. 2nd 事件发生在 6000 之前,并且由于事件 2 而执行回调。在此处发送响应。
  3. timeout 完成,传递给 setTimeout 的挂起函数执行回调,该回调将再次发送响应,并且在响应发送后无法将标头发送到响应。

解决方案

一个基本的解决方案是检查传递给设置超时的函数中的标志变量是否发生2nd事件。

function myFunction(myVar_1, myVar_2, callback){

    let executed = false;
    listenOnSocket.someEvent(myVar_1,
        function(error, event) {
            if(!executed){
            executed = true
            if (error) callback(null, error);
            else setTimeout(function() {
                       callback(event, null);
                    }, 6000);
        }
       }
    );    

    listenOnSocket.someEvent(myVar_2,
        function(error, event) {
            if(!executed){
            executed = true;
            if (!error) callback(event, null); 
            else callback(null, error);
        }
       }
    );

};

【讨论】:

  • 并且可能有一个标志并在您的任何事件被触发时设置它,并在调用回调之前检查它,这样一旦调用它就不会被调用。基本上你必须确保它在被调用后不再被调用。
  • 这个错误是由于多次执行回调引起的。你必须避免这种情况。
  • 我认为 cmets 对于未来的用户来说是一个很好的参考来源。所以最好不要删除那些。
  • 我不明白为什么会这样。你的第一个版本对我来说更有意义。在这种情况下,如果第一个事件首先被抛出并且 event if setTimeout 正在停止回调,则无法执行第二个事件,因为 executed 已经是 True!?
  • 旧版本没有涵盖所有情况以阻止回调被多次调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-27
  • 2017-07-14
  • 2016-08-21
  • 2012-05-14
  • 1970-01-01
  • 2012-10-22
  • 1970-01-01
相关资源
最近更新 更多