2017-10-17 16 views
-2

私は自分のノードJSでコールバック地獄を避けるために私のdamndestを試みています。しかし、私は多数のAPI要求を作成し、これらをデータベースに挿入しようとしています。ノードJS Apiのループでの要求

私のここでの問題は、forループが実行され、リクエストとデータベースの挿入が完了する前に私が増分することです。

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

'i'インクリメントは、あなたのケースで問題を引き起こすべきではありません。あなたの問題はおそらく他のものです。 –

答えて

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

を約束:あなたはこのコードを使用することになり、以下のすべてのオプションで

、 Bluebird Promiseライブラリ、Promise.map()を使用できます配列を反復するには、concurrencyオプションを渡して、同時に飛行している非同期呼び出しの数を制御します。これは、データベースまたはターゲットAPIホストの圧倒的な増加を防ぎ、最大メモリ使用量を制御するのに役立ちます。標準ES6を使用して

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

は、あなたがそのような順序でデータベースに挿入するなど、いくつかの理由のためにそれらをシリアル化する必要がある場合、あなたはこのようにそれを行うことができます

をお約束します。呼び出し、ブルーバードが

ブルーバードが直列に配列を繰り返し処理Promise.mapSeries()を有する約束使用直列に

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

:以下に示す.reduce()パターンは標準ES6を用いてアレイ上約束操作をシリアル化するための古典的な方法であります手作業よりも簡単な配列の各項目に約束を返す関数です。

Promise.mapSeries(data, apiCall).then(() => { 
    // all done here 
}).catch(err => { 
    // error here 
}); 
関連する問題