2017-10-17 2 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' incrementing이 문제를 일으키지 않아야합니다. 너의 문제는 다른 것 같다. –

답변

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 호스트를 압도하지 않고 최대 메모리 사용을 제어하는 ​​동시에 수행중인 비동기 호출 수를 제어 할 수 있습니다. 당신은 순서대로 데이터베이스에 삽입으로 어떤 이유를 직렬화해야하는 경우 표준 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 
});