2016-03-18 68 views
0

我正在研究包含Request module的Node應用程序。我需要發出多個請求,然後在全部完成時執行一個操作。在這個時候,我有:獲取多個請求

const request = require('request'); 

let urls = [GetUrl('id1'), GetUrl('idX'), ...); 
for (let url of urls) { 
    let u = request.get(url); 
    // now what? 
} 

我想不通什麼request.get返回。我知道它是異步運行的。但是我不能說它是ES6的承諾,還是一些承諾庫或其他的東西。

任何人都可以告訴我在所有請求完成後如何執行操作?

謝謝!

+0

request.get在回調函數中返回一個[http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse) – ZimSystem

回答

0

Bluebird具有允許「調節」的附加好處。

var Promise = require('bluebird'); 
var request = require('request-promise'); // since we'll be using promises 

Promise.map(arrayOfUrls, function(url){ 
    return request(url) 
     .then(function(data){ 
      return JSON.parse(data);  // format/manipulate your data 
     }) 
}).then(function(results){ 
    // results will be an array of JSON objects 
}) 

這將派發所有的請求一樣快,節點可以處理它們。如果這是你自己的服務器,這可能是好的,但要防止出現「太多錯誤的請求」,以下內容添加到您的通話map

Promise.map(arrayOfUrls, function, { concurrency: 4 }); 
// no more than 4 requests will run at once. Thanks Bluebird 
0

您可以使用q.js到promisfy get函數,等待所有作業完成

var Q = require("q"); 

var job = function(id) { 
    return Q.nbind(reqest.get, GetUrl(id)); 
}; 

let urls = [job('id1'), job('idX'), ...]); 
Q.all(urls) 
.then(function(values) { 
    ///do something here 
}) 
0

如果您需要等待所有的答覆,你不能使用常規的循環。而且因爲你在陣列中的所有網址,最好使用async.each

async.each(urls, function(url, eachCallback) { 
    request.get(url, function(err) { 
    // do something else 
    eachCallback(); 
    } 
}, function(err) { 

    // Done 
} 

基本上,async.each接受三個參數:

  1. 網址 - 項目的數組迭代
  2. func1 - 作爲每個項目執行任務的函數。從陣列
  3. eachCallback的項目 - -
    • 網址的回調函數爲你調用,只要你想說嘿,這任務是:只要調用這個函數,兩個參數一起傳遞完成了!
  4. FUNC2 - 一旦你遍歷所有的項目,所有eachCallback函數被調用,將執行一個功能。

請注意,人們往往會忘記在任務功能中調用eachCallback。這將導致func2未被執行。


如果你不想同時做到這一點。您可以改用async.eachSeries。它做同樣的事情,除了順序調用任務功能,並且只有在您致電eachCallback後。


如果您想繼續使用併發任務。您可能要考慮使用async.eachLimiteachLimiteach之間的差異是,eachLimit需要傳遞爲參數#2的數字:(async.eachLimit(urls, 10, func1, func2))。

這是一個很好的做法,尤其是如果你正在做耗盡機器資源的事情(比如做HTTP請求)。我在上一段中給出的例子將同時執行10個並行執行func1


您可以在async庫存儲庫中閱讀更多信息。

0

可以使用co了。它是基於發電機的。

var co = require('co'); 
var request = require('request-promise'); 

co(function *() { 
    var urls = ['http://a', 'http://b']; 
    var results = yield urls.map(x => request(x)); 
    console.log(results); 
}); 

順便說一句,你可以使用bluebird爲plomisify現有的回調樣式庫。

var co = require('co'); 
var promisifyAll = require('bluebird').promisifyAll; 
var request = promisifyAll(require('request'), {multiArgs: true}); 

co(function *() { 
    var urls = ['http://a', 'http://b']; 
    var results = yield urls.map(x => request.getAsync(x)); 
    console.log(results.map(x => [x[0].statusCode, x[1]])); 
}); 

即使您將使用ES7 async/await,更改也很小。 目前,以下需求巴別。

import 'babel-polyfill'; 
import request from 'request-promise'; 

(async() => { 
    let urls = ['http://foldl.com/', 'http://pig-brewing.com']; 
    let results = await Promise.all(urls.map(x => request(x))); 
    console.log(results); 
})();