NodeJS event handling mechanism for a use case

时间:2015-12-10 01:19:17

标签: javascript node.js

Imagine I have the following logic implemented in NodeJS

{
    for(list of objects)
    {
        REST API call (callback)
    }

    function callback(){
        if(responseCode != 200)
        {
            setTimeout(function() {
                //try again
                REST API call (callback)
            }, 5000);
        }
        else
        {
          //do something
        }
    }
}

Given NodeJS is single-threaded and event based, if the REST API response for object 1 is not 200, timeout will be triggered, in that case will object 2 be able to access the else loop given object 1 callback is still sleeping for 5000 milliseconds ? If yes, how does it work that way ?

2 个答案:

答案 0 :(得分:2)

Javascript是单线程(i,e)任何一个进程。定时器的工作方式是将它们置于具有用户指定的延迟的回调队列中。队列的主进程监视器在指定的持续时间内相应地触发回调。如果你想了解更多关于js引擎是如何工作的话,我建议你去看看。 https://youtu.be/8aGhZQkoFbQ

答案 1 :(得分:1)

对于节点和浏览器,无法保证AJAX调用按顺序完成...例如在

之后
rest_api_call("doit", 1, function(result){ console.log("Result 1"); });
rest_api_call("doit", 2, function(result){ console.log("Result 2"); });
rest_api_call("doit", 3, function(result){ console.log("Result 3"); });

即使一切正常(即如果没有错误),输出序列也很可能不会是1,2,3。

一旦进行了异步调用,它就会被简单地添加到等待响应的无序调用池中......无论哪个答案首先出现都是第一次服务。

简化模型的工作原理

function async_call(url, data, result_cback, error_cback) {
    start_new_thread(handler, [url, data, result_cback, error_cback]);
}

function handler(url, data, result_cback, error_cback) {
    try {
        var reply = sync_send_request(url, data);
        async_queue.push([result_cback, reply]);
    } catch(err) {
        async_queue.push([error_cback, err]);
    }
}

function main_loop() {
    for(;;) {
        if (async_queue.length) {
            var acall = async_queue.shift();
            acall[0](acall[1]);
        } else if (timeouts.length && now() > timeouts[0][0]) {
            var tcall = timeouts.shift();
            tcall[1](tcall[2]);
        } else if (mouse_moved) {
            ...
        } else if (needs_repaint) {
            ...
        } else {
            take_a_nap();
        }
    }
}