programing

루프용 Javascript 내부의 비동기 프로세스

css3 2023. 7. 24. 22:43

루프용 Javascript 내부의 비동기 프로세스

다음 형식의 이벤트 루프를 실행하고 있습니다.

var i;
var j = 10;
for (i = 0; i < j; i++) {

    asynchronousProcess(callbackFunction() {
        alert(i);
    });
}

숫자 0부터 10까지 일련의 경고를 표시하려고 합니다.문제는 콜백 함수가 트리거될 때까지 루프가 이미 몇 번 반복되어 더 높은 값을 표시한다는 것입니다.i이 문제를 해결하는 방법에 대한 추천 사항이 있습니까?

for모든 비동기 작업이 시작되는 동안 루프가 즉시 실행되어 완료됩니다.의 어느 때, 이 루 미 인 프 의 덱 스 변 의 수 신 때 할 호 고 출 하 을 료 콜 백 완 래 에i모든 콜백에 대해 마지막 값이 됩니다.

는 이유는그 때문입니다.for루프는 비동기 콜백을 나중에 호출하기 때문에 루프의 다음 반복으로 계속하기 전에 비동기 작업이 완료될 때까지 기다리지 않습니다.따라서 루프는 반복을 완료한 다음 이러한 비동기 작업이 완료되면 콜백이 호출됩니다.따라서 루프 인덱스는 "완료"되고 모든 콜백에 대한 최종 값에 저장됩니다.

이 문제를 해결하려면 각 콜백에 대해 루프 인덱스를 개별적으로 저장해야 합니다.자바스크립트에서, 그렇게 하는 방법은 함수 폐쇄로 캡처하는 것입니다.이를 위해 특별히 인라인 함수 폐쇄를 만들거나(아래 첫 번째 예제) 인덱스를 전달하는 외부 함수를 생성하여(아래 두 번째 예제) 인덱스를 고유하게 유지할 수 있습니다.

Javascript를 최신 2016년 버전을 사용할 수 .let정하자면을 for 고유하게 입니다.for루프(아래 세 번째 구현).그러나 이 기능은 ES6 구현의 최신 구현 기능이므로 실행 환경에서 해당 옵션을 지원하는지 확인해야 합니다.

.forEach()를 사용하여 자체 함수 폐쇄를 생성하므로 반복합니다.

someArray.forEach(function(item, i) {
    asynchronousProcess(function(item) {
        console.log(i);
    });
});

IIF를 사용하여 자체 함수 폐쇄 만들기

var j = 10;
for (var i = 0; i < j; i++) {
    (function(cntr) {
        // here the value of i was passed into as the argument cntr
        // and will be captured in this function closure so each
        // iteration of the loop can have it's own value
        asynchronousProcess(function() {
            console.log(cntr);
        });
    })(i);
}

외부 함수 생성 또는 수정 및 변수 전달

이 수할정경을 할 수 .asynchronousProcess()함수, 그러면 당신은 그냥 그 안에 값을 전달하고 그것을 가질 수 있습니다.asynchronousProcess()다음과 같이 cntr을 콜백으로 다시 기능시킵니다.

var j = 10;
for (var i = 0; i < j; i++) {
    asynchronousProcess(i, function(cntr) {
        console.log(cntr);
    });
}

ES6 사용하기let

ES6를 ES6의 Javascript를 할 수 .let의 신의에for다음과 같은 루프:

const j = 10;
for (let i = 0; i < j; i++) {
    asynchronousProcess(function() {
        console.log(i);
    });
}

let로선된으로 함.for이와 같은 루프 선언은 고유한 값을 생성합니다.i루프의 각 호출에 대해(사용자가 원하는 것).

약속 및 비동기/대기를 사용하여 직렬화

, 사용자는 를 에서 실행되고 .async그리고.await그러면 더 많은 선택권이 있습니다.

async function someFunction() {
    const j = 10;
    for (let i = 0; i < j; i++) {
        // wait for the promise to resolve before advancing the for loop
        await asynchronousProcess();
        console.log(i);
    }
}

이렇게 하면 한 번만 전화를 걸 수 있습니다.asynchronousProcess()한 번에 비행 중이고for루프는 각각이 끝날 때까지 전진하지도 않습니다.이는 비동기 작업을 모두 병렬로 실행했던 이전 체계와는 다르므로 원하는 설계에 전적으로 의존합니다. 참고:await약속과 함께 작동하므로 비동기 작업이 완료되면 함수가 해결/해제된 약속을 반환해야 합니다.또한 다음을 사용하기 위해 참고하십시오.await하는 함수는 반드시 포함함선합니야다해로 .async.

하고 비기작실사행용여하를 합니다.Promise.all()대로

 function someFunction() {
     let promises = [];
     for (let i = 0; i < 10; i++) {
          promises.push(asynchonousProcessThatReturnsPromise());
     }
     return Promise.all(promises);
 }

 someFunction().then(results => {
     // array of results in order here
     console.log(results);
 }).catch(err => {
     console.log(err);
 });

async await여기에 있습니다(ES7). 그래서 당신은 이제 이런 종류의 일들을 매우 쉽게 할 수 있습니다.

  var i;
  var j = 10;
  for (i = 0; i < j; i++) {
    await asycronouseProcess();
    alert(i);
  }

기억하세요, 이것은 다음과 같은 경우에만 작동합니다.asycronouseProcess하는 중입니다.Promise

한다면asycronouseProcess할 수 없는 를하도록 할 수 있습니다.Promise

function asyncProcess() {
  return new Promise((resolve, reject) => {
    asycronouseProcess(()=>{
      resolve();
    })
  })
}

다음 이 을 런그음 다 바 줄 꿉 니 다 을 이await asycronouseProcess();타고await asyncProcess();

조사하기 전에 먼저 이해해야 합니다(지원에 대한 내용도 참조).async await)

이것을 고치는 방법에 대해 추천할 만한 것이 있습니까?

여러명.바인딩을 사용할 수 있습니다.

for (i = 0; i < j; i++) {
    asycronouseProcess(function (i) {
        alert(i);
    }.bind(null, i));
}

또는 브라우저가 let를 지원하는 경우(다음 ECMA스크립트 버전이 될 예정이지만 파이어폭스는 잠시 후 이미 지원) 다음과 같은 기능을 제공할 수 있습니다.

for (i = 0; i < j; i++) {
    let k = i;
    asycronouseProcess(function() {
        alert(k);
    });
}

아니면, 당신은 할 수 있습니다.bind수동으로 (브라우저가 지원하지 않지만 심을 구현할 수 있는 경우에는 위의 링크에 있어야 합니다.)

for (i = 0; i < j; i++) {
    asycronouseProcess(function(i) {
        return function () {
            alert(i)
        }
    }(i));
}

나는 보통 선호합니다.let할 수 Firefox ), 그렇지 않은 경우에는 "Firefox 파일"("Firefox 파일"), "Firefox 파일"이 .bind또는 컨텍스트 개체가 필요 없는 사용자 지정 카레 기능입니다.

var i = 0;
var length = 10;

function for1() {
  console.log(i);
  for2();
}

function for2() {
  if (i == length) {
    return false;
  }
  setTimeout(function() {
    i++;
    for1();
  }, 500);
}
for1();

여기에 예상되는 것에 대한 샘플 기능적 접근법이 있습니다.

ES2017: 약속을 반환하는 함수(예: XHRPost) 안에 비동기 코드를 감쌀 수 있습니다(약속 안에 비동기 코드).

그런 다음 마법의 Wait 키워드를 사용하여 루프 내부의 함수(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);       
    });
 }
 
(async () => {
    for (let i = 1; i < 5; i++) {
        await XHRpost(i);
       }
})();

JavaScript 코드는 단일 스레드에서 실행되므로 페이지 가용성에 심각한 영향을 주지 않고 다음 반복을 시작하기 전에 첫 번째 반복이 완료될 때까지 기다리는 것을 기본적으로 차단할 수 없습니다.

해결책은 여러분이 정말로 필요로 하는 것에 달려 있습니다. @ @Simon의 @Simon의 입니다.i당신의 비동기 프로세스는 좋은 것입니다.

언급URL : https://stackoverflow.com/questions/11488014/asynchronous-process-inside-a-javascript-for-loop