簡體   English   中英

實現node.js回調的超時

[英]Implementing timeouts for node.js callbacks

這是node.js中的典型情況:

asyncFunction(arguments, callback);

asynFunction完成時,將調用callback 我看到這個模式的一個問題是,如果asyncFunction 永遠不會完成(並且asynFunction沒有內置的超時系統),那么永遠不會調用callback 更糟糕的是,似乎callback無法確定asynFunction永遠不會返回。

我想實現一個“超時”,由此,如果callback尚未調用由asyncFunction 1秒鍾之內,那么callback會自動被調用,並假設asynFunction已經出錯了。 這樣做的標准方法是什么?

我不熟悉任何執行此操作的庫,但是自己連接起來並不困難。

// 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();
  }
});

您可能需要提出自己的解決方案。 喜歡

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;
}

然后

asyncFunction(arguments, callBackWithATimeout(callback, 2000));

你可以這樣做:

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;
}

用法:

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

DEMO

但請注意以下事項:

  • 當您調用ensureExecution ,會立即啟動超時,因此您無法緩存該函數引用。

  • 傳遞給回調的參數會有所不同。 例如, asyncFunction可能會在成功時將一些參數傳遞給callback ,但如果超時調用該函數,則不會傳遞任何參數。 你必須記住這一點。 在這種情況下,您還可以提供應該調用函數的默認參數:

     function ensureExecution(func, timeout, args, this_obj) { // ... timer = setTimeout(function() { run.apply(this_obj, args); }, timeout); //... } 

我遇到了同樣的問題,內容腳本嘗試在BG擴展准備好之前打開BG擴展上的端口。 解決方法是等待BG擴展程序回復消息並重復此操作直到成功。 以下是代碼段。

內容腳本:

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擴展

  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});
    }
  });

在我的情況下,它通常在第一個100毫秒延遲后。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM