Implementing timeouts for node.js callbacks

前端 未结 4 562
执念已碎
执念已碎 2020-12-25 11:07

This is a typical situation in node.js:

asyncFunction(arguments, callback);

When asynFunction completes, callback

相关标签:
4条回答
  • 2020-12-25 11:43

    You could do something like this:

    function ensureExecution(func, timeout) {
        var timer, run, called = false;
    
        run = function() {   
            if(!called) {
                clearTimeout(timer);
                called = true;
                func.apply(this, arguments);
            }   
        };
    
        timer = setTimeout(run, timeout);
        return run;
    }
    

    Usage:

    asyncFunction(arguments, ensureExecution(callback, 1000));
    

    DEMO

    But note the following:

    • The timeout is started immediately when you call ensureExecution, so you cannot cache that function reference.

    • The arguments passed to the callback will differ. For example asyncFunction might pass some arguments to callback upon success, but if the function is called by the timeout, no arguments will be passed. You have to keep that it mind. You could also provide default arguments with which the function should be called in this case:

      function ensureExecution(func, timeout, args, this_obj) {
          // ...
          timer = setTimeout(function() {
              run.apply(this_obj, args);
          }, timeout);
          //...
      }
      
    0 讨论(0)
  • 2020-12-25 11:58

    You probably need to come out with a solution of your own. Like

    function callBackWithATimeout (callback, timeout) {
      var run, timer;
      run = function () {
        if (timer) {
          clearTimeout(timer);
          timer = null;
          callback.apply(this, arguments);
        }
      };
      timer = setTimeout(run, timeout, "timeout");
      return run;
    }
    

    and then

    asyncFunction(arguments, callBackWithATimeout(callback, 2000));
    
    0 讨论(0)
  • 2020-12-25 12:01

    I'm not familiar with any libraries that do this, but it's not hard to wire up yourself.

    // Setup the timeout handler
    var timeoutProtect = setTimeout(function() {
    
      // Clear the local timer variable, indicating the timeout has been triggered.
      timeoutProtect = null;
    
      // Execute the callback with an error argument.
      callback({error:'async timed out'});
    
    }, 5000);
    
    // Call the async function
    asyncFunction(arguments, function() {
    
      // Proceed only if the timeout handler has not yet fired.
      if (timeoutProtect) {
    
        // Clear the scheduled timeout handler
        clearTimeout(timeoutProtect);
    
        // Run the real callback.
        callback();
      }
    });
    
    0 讨论(0)
  • 2020-12-25 12:04

    I ran into the same problem with a content script trying to open the port on the BG extension before the BG extension was ready. A work around was to wait for the BG extension to reply to a message and repeat this till successful. Here are the code snippets.

    Content Script:

    var nTimes     = 10;
    var bIsReady = false;
    checkBGReady();
    function checkBGReady() {
      if (!bIsReady) {
        chrome.runtime.sendMessage({msgText: "hello "+nTimes}, function(response) {
          if (response && response.ack) {
            console.log("have response:"+response.ack+" "+nTimes);
            bIsReady = true;
            // continue with initialization
            bootStrap(sURL);
            checkReady();
          } else {
            console.log("have no ack response %o",response);
          }
        });
      }
      nTimes -= 1;
      if (nTimes > 0 && !bIsReady) {
        setTimeout(checkBGReady,100);
      }
    }
    

    BG Extension

      chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
        console.log(sender.tab ?"from a content script:" + sender.tab.url :"from the extension");
        if (request.msgText) {
          console.log("Have msg "+request.msgText);
           sendResponse({ack: "have contact "+request.msgText});
        }
      });
    

    In my case it usually took after the first 100ms delay.

    0 讨论(0)
提交回复
热议问题