2017-10-17 117 views
-2

我想我最害怕避免與我的節點JS的回調地獄。但我試圖做大量的API請求,並將其插入到我的數據庫中。節點中的JS Api請求循環

我的問題在這裏(當然)是我的for-loop在我完成我的請求和數據庫插入之前運行並遞增。

for(var i = 0; i <= 1 ; i++){ 
    apiRequest = data[i]; 
    apicall(apiRequest); 
} 


function apicall(urlApi){ 
    request((urlApi), function(error, response, body){ 
     if(error){ 
      console.log("error"); 
     } else if(!error && response.statusCode == 200){ 
      var myobj = JSON.parse(body); 
      dbInsert(myobj); 
     } 
    }); 
} 

function dbInsert(obj) { 
    //insert into database 
} 

如果其他人會來這個問題,我可以真實地建議我這篇文章,我通過joshvermaire讀取響應後發現:

http://www.sebastianseilund.com/nodejs-async-in-practice

+0

查看async/await - 它們將允許您在apicall處於活動狀態時暫停。 – theGleep

+0

'我'遞增不應該在你的情況下造成問題。你的問題可能是別的。 –

回答

1

我建議使用類似async.each 。然後,你可以這樣做:

async.each(data, function(apiRequest, cb) { 
    apicall(apiRequest, cb); 
}, function(err) { 
    // do something after all api requests have been made 
}); 

function apicall(urlApi, cb){ 
    request((urlApi), function(error, response, body){ 
     if(error){ 
      console.log("error"); 
      cb(error); 
     } else if(!error && response.statusCode == 200){ 
      var myobj = JSON.parse(body); 
      dbInsert(myobj, cb); 
     } 
    }); 
} 

function dbInsert(obj, cb) { 
    doDBInsert(obj, cb); 
} 

dbInsert方法完成,確保cb回調被調用。如果您需要一系列操作,請參閱async.eachSeries

+0

這將如何解決用戶的問題?用戶的問題究竟是什麼? –

1

有幾種方法可以解決這類問題。首先,如果您可以並行運行所有API調用(同時全部都在運行),並且它們在數據庫中插入的順序無關緊要,那麼您可以通過這樣做獲得更快的結果(vs 。按順序將它們序列化)。

在下面的所有選項,你可以使用此代碼:

const rp = require('request-promise'); 

function apicall(urlApi){ 
    return rp({url: urlApi, json: true}).then(function(obj){ 
     return dbInsert(obj); 
    }); 
} 

function dbInsert(obj) { 
    //insert into database 
    // return a promise that resolves when the database insertion is done 
} 

並行使用ES6標準少輝

let promises = []; 
for (let i = 0; i <= data.length; i++) { 
    promises.push(apicall(data[i])); 
} 

Promise.all(promises).then(() => { 
    // all done here 
}).catch(err => { 
    // error here 
}); 

使用藍鳥無極圖書館

隨着並行藍鳥諾言庫,你可以使用Promise.map()迭代你的數組,你可以傳遞concurrency選項來控制同時有多少個異步調用正在運行,這可能會使數據庫或目標API主機不堪重負,並可能有助於控制最大內存使用量。

Promise.map(data, apiCall, {concurrency: 10}).then(() => { 
    // all done here 
}).catch(err => { 
    // error here 
}); 

在系列採用標準ES6少輝

如果你有連載他們出於某種原因,如爲了插入數據庫,那麼你就可以是這樣做的。下面顯示的.reduce()模式是使用標準ES6陣列上連載的承諾操作的經典方式:

data.reduce(data, (p, item) => { 
    return p.then(() => { 
     return apicall(item); 
    }); 
}, Promise.resolve()).then(() => { 
    // all done here 
}).catch(err => { 
    // error here 
}); 

使用串聯的藍鳥公司承諾

藍鳥有Promise.mapSeries()迭代訪問串聯數組,調用一個函數在數組中的每個項目上返回一個promise,這比手動操作要簡單一點。

Promise.mapSeries(data, apiCall).then(() => { 
    // all done here 
}).catch(err => { 
    // error here 
});