잡동사니

반응형

질문

비동기 적으로 작업을 수행하는 메서드를 호출하는 루프가 있습니다. 이 루프는 메서드를 여러 번 호출 할 수 있습니다. 이 루프 후에는 모든 비동기 작업이 완료 될 때만 실행해야하는 또 다른 루프가 있습니다. 그래서 이것은 내가 원하는 것을 보여줍니다.

for (i = 0; i < 5; i++) {
    doSomeAsyncStuff();    
}

for (i = 0; i < 5; i++) {
    doSomeStuffOnlyWhenTheAsyncStuffIsFinish();    
}

나는 Promise에별로 익숙하지 않은데 누구든지 나를 도와 줄 수 있습니까?

이것이 내 doSomeAsyncStuff () 의 작동 방식입니다.

function doSomeAsyncStuff() {
    var editor = generateCKEditor();
    editor.on('instanceReady', function(evt) {
        doSomeStuff();
        // There should be the resolve() of the promises I think.
    })
}

아마도 다음과 같이해야합니다.

function doSomeAsyncStuff() {
    var editor = generateCKEditor();
    return new Promise(function(resolve,refuse) {
        editor.on('instanceReady', function(evt) {
            doSomeStuff();
            resolve(true);
        });
    });
}

하지만 구문을 잘 모르겠습니다.


답변1

Promise.all ( 사양 , MDN )이를 위해 : 여러 개의 개별 Promise을 수락하고 사용자가 제공 한 모든 Promise이 해결되면 해결되는 단일 Promise을 되돌려주고 그중 하나가 거부되면 거부됩니다.

따라서 doSomeAsyncStuff 가 promise를 반환하도록하면 다음과 같습니다.

var promises = [];

for(i=0;i<5;i++){
    promises.push(doSomeAsyncStuff());
}

Promise.all(promises)
    .then(() => {
        for(i=0;i<5;i+){
            doSomeStuffOnlyWhenTheAsyncStuffIsFinish();    
        }
    })
    .catch((e) => {
        // handle errors here
    });

Axel Rauschmayer는 여기 에 Promise에 대한 좋은 기사를 제공합니다.

예 : { console.log ( "모두 완료", 결과); }) .catch ((e) => { // 여기에서 오류 처리 });}테스트();"rel ="noreferrer "> Babel의 REPL에 대한 라이브 카피 :

 function doSomethingAsync(value) {
      return new Promise((resolve) => {
        setTimeout(() => {
          console.log("Resolving " + value);
          resolve(value);
        }, Math.floor(Math.random() * 1000));
      });
    }
    
    function test() {
      let i;
      let promises = [];
      
      for (i = 0; i < 5; ++i) {
        promises.push(doSomethingAsync(i));
      }
      
      Promise.all(promises)
          .then((results) => {
            console.log("All done", results);
          })
          .catch((e) => {
              // Handle errors here
          });
    }
    
    test();

(Didn't bother with .catch on that, but you do want .catch on your real-world ones, as shown earlier.)

샘플 출력 ( Math.random 때문에 먼저 끝나는 것이 다를 수 있음) :

Resolving 3
Resolving 2
Resolving 1
Resolving 4
Resolving 0
All done [0,1,2,3,4]


답변2

재사용 가능한 함수는이 패턴에 대해 잘 작동합니다.

function awaitAll(count, asyncFn) {
  const promises = [];

  for (i = 0; i < count; ++i) {
    promises.push(asyncFn());
  }

  return Promise.all(promises);
}

OP 예 :

awaitAll(5, doSomeAsyncStuff)
  .then(results => console.log('doSomeStuffOnlyWhenTheAsyncStuffIsFinished', results))
  .catch(e => console.error(e));

관련 패턴은 배열을 반복하고 각 항목에 대해 비동기 작업을 수행합니다.

function awaitAll(list, asyncFn) {
  const promises = [];

  list.forEach(x => {
    promises.push(asyncFn(x));
  });

  return Promise.all(promises);
}

예:

const books = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }];

function doSomeAsyncStuffWith(book) {
  return Promise.resolve(book.name);
}

awaitAll(books, doSomeAsyncStuffWith)
  .then(results => console.log('doSomeStuffOnlyWhenTheAsyncStuffIsFinished', results))
  .catch(e => console.error(e));


답변3

const doSomeAsyncStuff = async (funcs) => {
  const allPromises = funcs.map(func => func());
  return await Promise.all(allPromises);
}

doSomeAsyncStuff([
  () => new Promise(resolve => setTimeout(() => resolve(), 100)),
  () => new Promise(resolve => setTimeout(() => resolve(), 100)),
  () => new Promise(resolve => setTimeout(() => resolve(), 100)),
  () => new Promise(resolve => setTimeout(() => resolve(), 100)),
  () => new Promise(resolve => setTimeout(() => resolve(), 100)),
]);


답변4

여기에 명시된 답변을 이해하기 위해 내가 작성한 코드가 있습니다. for 루프에 몽구스 쿼리가 있으므로 여기에 asyncFunction 을 넣어 대신합니다. 누구에게나 도움이되기를 바랍니다. 이 script는 노드 또는 여러 Javascript runtime에서 실행할 수 있습니다.

let asyncFunction = function(value, callback)
{
        setTimeout(function(){console.log(value); callback();}, 1000);
}



// a sample function run without promises

asyncFunction(10,
    function()
    {
        console.log("I'm back 10");
    }
);


//here we use promises

let promisesArray = [];

let p = new Promise(function(resolve)
{
    asyncFunction(20,
        function()
        {
            console.log("I'm back 20");
            resolve(20);
        }
    );
});

promisesArray.push(p);


for(let i = 30; i < 80; i += 10)
{
    let p = new Promise(function(resolve)
    {
        asyncFunction(i,
            function()
            {
                console.log("I'm back " + i);
                resolve(i);
            }
        );
    });
    promisesArray.push(p);
}


// We use Promise.all to execute code after all promises are done.

Promise.all(promisesArray).then(
    function()
    {
        console.log("all promises resolved!");
    }
)


답변5

/*** Worst way ***/
for(i=0;i<10000;i++){
  let data = await axios.get(
    "https://yourwebsite.com/get_my_data/"
  )
  //do the statements and operations
  //that are dependant on data
}

//Your final statements and operations
//That will be performed when the loop ends

//=> this approach will perform very slow as all the api call
// will happen in series


/*** One of the Best way ***/

const yourAsyncFunction = async (anyParams) => {
  let data = await axios.get(
    "https://yourwebsite.com/get_my_data/"
  )
  //all you statements and operations here
  //that are dependant on data
}
var promises = []
for(i=0;i<10000;i++){
  promises.push(yourAsyncFunction(i))
}
await Promise.all(promises)
//Your final statement / operations
//that will run once the loop ends

//=> this approach will perform very fast as all the api call
// will happen in parallal



 

 

 

 

출처 : https://stackoverflow.com/questions/31426740/how-to-return-many-promises-in-a-loop-and-wait-for-them-all-to-do-other-stuff

반응형

이 글을 공유합시다

facebook twitter googleplus kakaoTalk kakaostory naver band