簡體   English   中英

node.js 多個異步函數

[英]node.js multiple asynchronous functions

var http = require('http');
var res = ["","",""];
for(i =2;i<5;i++){
   http.get(process.argv[i],function(response){
           response.setEncoding('utf8');
           str = "";
           count =i-2;
           response.on("data", function(data) {
                   str = str.concat(data);
           });
           response.on("end", function() {
                   res[count] = str;
                   console.log(count);
                   console.log(res[count]);
           });
   });
}

while(true) {
    if(res[0]!==""&&res[1]!==""&&res[2]!=="")
    {
           console.log(res[0]);
           console.log(res[1]);
           console.log(res[2]);
           break;
    }
}

我將使用三個 URL 作為前三個命令行參數。 我的工作是從每個 URL 中收集作為字符串的數據,並按照它們在命令行中出現的順序將它們打印到控制台。 現在代碼沒有打印任何東西,它陷入了無限循環。 怎么了?

代碼中有兩個問題。 首先,您在循環變量上有一個閉包,這使得值與 guvinder372 解釋的預期不同。 另見這個答案,其中討論了這個問題,這個答案演示一種更好的方式使用來解決這個問題Function.bind

第二個問題是你在最后設置你的while循環的方式。 該循環將持續運行,並且永遠不會允許http.get的回調函數運行。 相反,如果其他響應已經進入,則檢查回調,一旦所有三個響應都進入,打印輸出。

for(i =2;i<5;i++){
   http.get(process.argv[i],function(response){
           response.setEncoding('utf8');
           str = "";
           count =i-2;
           response.on("data", function(data) {
                   str = str.concat(data);
           });
           response.on("end", function() {
                   //Check here if responses are in
                   if(res[0]!==""&&res[1]!==""&&res[2]!=="") {
                   }
                   res[count] = str;
                   console.log(count);
                   console.log(res[count]);
           });
   });
}

問題是- 調用回調處理程序時, i 的值已經達到 5 並且對於所有回調處理程序執行它將保持為 5。

您需要重構代碼以將 i 的值傳遞給該調用方法

var http = require('http');
var res = ["","",""];
for(i =2;i<5;i++)
{
  callBackDefiner(i)
}

function callBackDefiner( i )
{
   http.get(process.argv[i],function(response){
           response.setEncoding('utf8');
           str = "";
           count =i-2;
           response.on("data", function(data) {
                   str = str.concat(data);
           });
           response.on("end", function() {
                   res[count] = str;
                   console.log(count);
                   console.log(res[count]);
           });
   });
}

您不能在不等待響應的情況下在for...loop循環中執行多個 http 請求。 要以現代方式編寫此代碼,您需要一些新的構造/模式,例如Promise 然后,您可以等待每個響應、收集響應並退出調用者。 舉個例子,看看我的 javascript 客戶端解決方案。 這也可以在Node.js進行少量工作,您只需更改在塊函數ExecutionBlock請求的方式即可。

假設我們有一個我們想要發送到一些 urls / 或不同 url 數組的參數數組,我們將使用Promise.all構造運行。

在以下代碼段中嘗試一下。

要了解如何將此解決方案應用於Node.js在此處查看我對http get 和 post 的實現,並在本文后面查看異步任務節點中更復雜的執行。

 var console = { log: function(s) { document.getElementById("console").innerHTML += s + "<br/>" } } // Simple XMLHttpRequest // based on https://davidwalsh.name/xmlhttprequest SimpleRequest = { call: function(what, response) { var request; if (window.XMLHttpRequest) { // Mozilla, Safari, ... request = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { request = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { request = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } } // state changes request.onreadystatechange = function() { if (request.readyState === 4) { // done if (request.status === 200) { // complete response(request.responseText) } else response(); } } request.open('GET', what, true); request.send(null); } } //PromiseAll var promiseAll = function(items, block) { var self = this; var promises = [], index = 0; items.forEach(function(item) { promises.push(function(item, i) { return new Promise(function(resolve, reject) { if (block) { block.apply(this, [item, index, resolve, reject]); } }); }(item, ++index)) }); return Promise.all(promises) }; //promiseAll // LP: deferred execution block var ExecutionBlock = function(item, index, resolve, reject) { SimpleRequest.call('https://icanhazip.com/', function(result) { if (result) { console.log("Response[" + index + "] " + result); resolve(result); } else { reject(new Error("call error")); } }) } arr = [1, 2, 3] promiseAll(arr, (item, index, resolve, reject) => { console.log("Making request [" + index + "]") ExecutionBlock(item, index, resolve, reject); }) .then((results) => { console.log(results) }) .catch((error) => { console.error(error) });
 <div id="console" />

對於通過PromisePromise.all應用於 node.js 的類似方法,請參閱我的問題here 這是關於以異步方式在節點中生成通用進程的執行。

這里有一個更復雜的例子展示了如何使用PromiseN * M http.get執行器中生成和鏈接多個級別的 http 調用執行。 因此,您將開始執行N請求,每個請求將啟動M請求,感謝Promise.all您將等待每個請求,等待第一個M所有結果,然后是N * M個請求響應數組的所有結果。

暫無
暫無

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

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