JavaScript의 for 루프 내에서 비동기 함수 호출
다음 코드가 있습니다.
for(var i = 0; i < list.length; i++){
mc_cli.get(list[i], function(err, response) {
do_something(i);
});
}
mc_cli
memcached 데이터베이스에 대한 연결입니다. 상상할 수 있듯이 콜백 함수는 비동기식이므로 for 루프가 이미 종료되었을 때 실행될 수 있습니다. 또한 이런 식으로 호출 할 때 do_something(i)
항상 for 루프의 마지막 값을 사용합니다.
이런 식으로 클로저로 시도했습니다
do_something((function(x){return x})(i))
그러나 분명히 이것은 항상 for 루프 인덱스의 마지막 값을 사용하고 있습니다.
또한 for 루프 전에 함수를 다음과 같이 선언하려고 시도했습니다.
var create_closure = function(i) {
return function() {
return i;
}
}
그리고 전화
do_something(create_closure(i)())
그러나 다시 성공하지 못했습니다. 반환 값은 항상 for 루프의 마지막 값입니다.
아무도 내가 폐쇄로 뭘 잘못하고 있는지 말해 줄 수 있습니까? 나는 그들을 이해한다고 생각했지만 이것이 작동하지 않는 이유를 알 수 없습니다.
배열을 통해 실행 중이므로 forEach
목록 항목을 제공하는 항목과 콜백의 인덱스를 간단히 사용할 수 있습니다 . 반복에는 자체 범위가 있습니다.
list.forEach(function(listItem, index){
mc_cli.get(listItem, function(err, response) {
do_something(index);
});
});
이것은 비동기 함수 내부 루프 패러다임이며 일반적으로 즉시 호출 된 익명 함수를 사용하여 처리합니다. 이렇게하면 인덱스 변수의 올바른 값으로 비동기 함수가 호출됩니다.
좋아요. 따라서 모든 비동기 함수가 시작되고 루프가 종료됩니다. 이제 이러한 함수가 언제 완료되는지, 비동기 적 특성으로 인해 또는 완료 될 순서를 알 수 없습니다. 실행하기 전에 이러한 모든 함수가 완료 될 때까지 기다려야하는 코드가있는 경우 완료된 함수 수를 간단히 계산하는 것이 좋습니다.
var total = parsed_result.list.length;
var count = 0;
for(var i = 0; i < total; i++){
(function(foo){
mc_cli.get(parsed_result.list[foo], function(err, response) {
do_something(foo);
count++;
if (count > total - 1) done();
});
}(i));
}
// You can guarantee that this function will not be called until ALL of the
// asynchronous functions have completed.
function done() {
console.log('All data has been loaded :).');
}
나는 이것이 오래된 스레드라는 것을 알고 있지만 어쨌든 내 대답을 추가합니다. ES2015 let
에는 반복마다 루프 변수를 리 바인딩하는 기능이 있으므로 비동기 콜백에서 루프 변수의 값을 유지하므로 다음 중 하나를 시도해 볼 수 있습니다.
for(let i = 0; i < list.length; i++){
mc_cli.get(list[i], function(err, response) {
do_something(i);
});
}
그러나 어쨌든 ES2015 기능이며 모든 브라우저 및 구현을 지원하지 않을 수 있으므로 forEach
즉시 호출 된 기능을 사용하여 클로저 를 사용 하거나 만드는 let
것이 좋습니다. 에서 여기 에서 Bindings ->let->for/for-in loop iteration scope
나는 그것이까지 지원되지 않습니다 볼 수 있습니다 에지 (13) 심지어까지 파이어 폭스 49 (I이 브라우저에서 확인하지 않은 경우). 심지어 Node 4에서는 지원되지 않는다고 말하지만 개인적으로 테스트 한 결과 지원되는 것 같습니다.
꽤 가까웠지만 get
콜백에 넣는 대신 클로저를 전달해야합니다 .
function createCallback(i) {
return function(){
do_something(i);
}
}
for(var i = 0; i < list.length; i++){
mc_cli.get(list[i], createCallback(i));
}
async/await
구문을 사용하여 이것을 시도 하고Promise
(async function() {
for(var i = 0; i < list.length; i++){
await new Promise(next => {
mc_cli.get(list[i], function(err, response) {
do_something(i); next()
})
})
}
})()
이렇게하면 next()
기능이 트리거 될 때까지 각주기에서 루프가 중지됩니다.
ES2017 : 약속을 반환하는 함수 (예 : XHRPost) 내부에 비동기 코드를 래핑 할 수 있습니다 (약속 내부의 비동기 코드).
그런 다음 for 루프 내에서 마법의 Await 키워드를 사용하여 함수 (XHRPost)를 호출합니다. :)
let http = new XMLHttpRequest();
let url = 'http://sumersin/forum.social.json';
function XHRpost(i) {
return new Promise(function(resolve) {
let params = 'id=nobot&%3Aoperation=social%3AcreateForumPost&subject=Demo' + i + '&message=Here%20is%20the%20Demo&_charset_=UTF-8';
http.open('POST', url, true);
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
http.onreadystatechange = function() {
console.log("Done " + i + "<<<<>>>>>" + http.readyState);
if(http.readyState == 4){
console.log('SUCCESS :',i);
resolve();
}
}
http.send(params);
});
}
for (let i = 1; i < 5; i++) {
await XHRpost(i);
}
루프 내에서 비동기 함수를 실행하고 싶지만 콜백이 실행 된 후에도 인덱스 또는 기타 변수를 유지하려면 코드를 IIFE (즉시 호출 된 함수 표현식)로 래핑 할 수 있습니다.
var arr = ['Hello', 'World', 'Javascript', 'Async', ':)'];
for( var i = 0; i < arr.length; i++) {
(function(index){
setTimeout(function(){
console.log(arr[index]);
}, 500);
ES6 (typescript)를 사용하면 async
및 의 이점을 사용할 수 있습니다 await
.
let list: number[] = [1, 2, 3, 4, 5];
// this is async fucntion
function do_something(counter: number): Promise<number> {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('called after ' + counter + ' seconds');
resolve(counter);
}, counter * 1000);
})
}
async function foo() {
// itrate over list and wait for when everything is finished
let data = await Promise.all(list.map(async i => await do_something(i)));
console.log(data);
}
foo();
ReferenceURL : https://stackoverflow.com/questions/13343340/calling-an-asynchronous-function-within-a-for-loop-in-javascript
'programing' 카테고리의 다른 글
Android에서만 코드를 통해 진행률 표시 줄 색상 변경 (0) | 2021.01.17 |
---|---|
코의 assert_raises를 사용하는 방법? (0) | 2021.01.17 |
java.lang.RuntimeException : Parcel에서 입력 채널 파일 설명자를 읽을 수 없습니다. (0) | 2021.01.16 |
HTML5 상용구 대 HTML5 재설정 (0) | 2021.01.16 |
Roslyn은 크로스 플랫폼입니까? (0) | 2021.01.16 |