programing

.forEach()가 완료될 때까지 기다리는 가장 좋은 방법

subpage 2023. 2. 23. 22:48
반응형

.forEach()가 완료될 때까지 기다리는 가장 좋은 방법

때때로 나는 기다릴 필요가 있다..forEach()주로 '완료' 함수에 대한 메서드입니다.이 방법은 다음과 같습니다.

$q.when(array.forEach(function(item){ 
    //iterate on something 
})).then(function(){ 
    //continue with processing 
});

이 방법이 다른 사람을 기다리는 최선의 방법은 아니라는 생각이 들지 않을 수 없다..forEach()완성할 수 있습니다.어떻게 하면 좋을까요?

내부에 비동기 코드가 없는 경우forEach,forEach는 비동기적이지 않습니다.예를 들어, 다음의 코드에서는,

array.forEach(function(item){ 
    //iterate on something 
});
alert("Foreach DONE !");

다음 시간 후에 경고가 표시됩니다.forEach끝났습니다.

그렇지 않은 경우(내부에는 비동기적인 것이 있습니다),forEach약속의 루프:

var bar = new Promise((resolve, reject) => {
    foo.forEach((value, index, array) => {
        console.log(value);
        if (index === array.length -1) resolve();
    });
});

bar.then(() => {
    console.log('All done!');
});

크레딧 : @rolando-benjamin-vaz-ferreira

ES6를 사용하여 이 작업을 수행하는 가장 빠른 방법은 이 기능을 사용하는 것입니다.for..of고리.

const myAsyncLoopFunction = async (array) => {
  const allAsyncResults = []

  for (const item of array) {
    const asyncResult = await asyncFunction(item)
    allAsyncResults.push(asyncResult)
  }

  return allAsyncResults
}

또는 이 모든 비동기 요구를 동시에 루프할 수 있습니다.Promise.all()다음과 같습니다.

const myAsyncLoopFunction = async (array) => {
  const promises = array.map(asyncFunction)
  await Promise.all(promises)
  console.log(`All async tasks complete!`)
}
var foo = [1,2,3,4,5,6,7,8,9,10];

실제로 루프 내에서 비동기적인 작업을 하고 있다면 약속으로 포장할 수 있습니다.

var bar = new Promise((resolve, reject) => {
    foo.forEach((value, index, array) => {
        console.log(value);
        if (index === array.length -1) resolve();
    });
});

bar.then(() => {
    console.log('All done!');
});

루프 내에 비동기 작업이 있어 대기할 경우.사용할 수 있습니다.for await

for await (const i of images) {
    let img = await uploadDoc(i);
};

let x = 10; //this executes after

각()은 아무것도 반환하지 않으므로 더 나은 방법은 다음과 같습니다.map()+Promise.all()

var arr = [1, 2, 3, 4, 5, 6]

var doublify = (ele) => {
  return new Promise((res, rej) => {
    setTimeout(() => {
        res(ele * 2)
    }, Math.random() ); // Math.random returns a random number from 0~1
  })
}

var promises = arr.map(async (ele) => {
  // do some operation on ele
  // ex: var result = await some_async_function_that_return_a_promise(ele)
  // In the below I use doublify() to be such an async function

  var result = await doublify(ele)
  return new Promise((res, rej) => {res(result)})
})

Promise.all(promises)
.then((results) => {
  // do what you want on the results
  console.log(results)
})

산출량

사용하다for of대신forEach. 이렇게.

for (const item of array) {
  //do something
}
console.log("finished");

"finished"는 루프가 종료된 후에 기록됩니다.

모든 forEach() 요소가 실행을 완료했는지 확인하기 위한 범용 솔루션입니다.

const testArray = [1,2,3,4]
let count = 0

await new Promise( (resolve) => {
  testArray.forEach( (num) => {
    try {
      //some real logic
      num = num * 2
    } catch (e) {
      // error handling
      console.log(e)
    } fanally {
      // most important is here
      count += 1
      if (count == testArray.length) {
        resolve()
      }
    }
  })  
})

이 생각은 인덱스를 사용하여 계산하는 답변과 동일합니다.그러나 실제로 오류가 발생하면 인덱스 방식이 올바르게 계산되지 않습니다.따라서 솔루션이 더욱 강력해집니다.

고마워

const array = [1, 2, 3];
const results = [];
let done = 0;

const asyncFunction = (item, callback) =>
  setTimeout(() => callback(item * 10), 100 - item * 10);

new Promise((resolve, reject) => {
  array.forEach((item) => {
    asyncFunction(item, (result) => {
      results.push(result);
      done++;
      if (done === array.length) resolve();
    });
  });
}).then(() => {
  console.log(results); // [30, 20, 10]
});

// or
// promise = new Promise(...);
// ...
// promise.then(...);

결과 배열의 결과 순서는 비동기 기능()이 각 항목에 대해 종료된 시간에 따라 원래 배열의 항목 순서와 다를 수 있습니다.

콜백을 포함하여 가능한 모든 고유 코드 브랜치 끝에 있는 카운터를 변경 및 체크합니다.예:

const fs = require('fs');

/**
 * @description Delete files older than 1 day
 * @param {String} directory - The directory to purge
 * @return {Promise}
 */
async function purgeFiles(directory) {
  const maxAge = 24*3600000;
  const now = Date.now();
  const cutoff = now-maxAge;

  let filesPurged = 0;
  let filesProcessed = 0;
  let purgedSize = 0;

  await new Promise( (resolve, reject) => {
    fs.readdir(directory, (err, files) => {
      if (err) {
        return reject(err);
      }
      if (!files.length) {
        return resolve();
      }
      files.forEach( file => {
        const path = `${directory}/${file}`;
        fs.stat(path, (err, stats)=> {
          if (err) {
            console.log(err);
            if (++filesProcessed === files.length) resolve();
          }
          else if (stats.isFile() && stats.birthtimeMs < cutoff) {
            const ageSeconds = parseInt((now-stats.birthtimeMs)/1000);
            fs.unlink(path, error => {
              if (error) {
                console.log(`Deleting file failed: ${path} ${error}`);
              }
              else {
                ++filesPurged;
                purgedSize += stats.size;
                console.log(`Deleted file with age ${ageSeconds} seconds: ${path}`);
              }
              if (++filesProcessed === files.length) resolve();
            });
          }
          else if (++filesProcessed === files.length) resolve();
        });
      });
    });
  });

  console.log(JSON.stringify({
    directory,
    filesProcessed,
    filesPurged,
    purgedSize,
  }));
}

// !!DANGER!! Change this line! (intentional syntax error in ,')
const directory = ,'/tmp'; // !!DANGER!! Changeme
purgeFiles(directory).catch(error=>console.log(error));

다른 버전에 비해 이 버전의 효율성은 잘 모르겠지만 최근 ForEach()에 비동기 함수가 있을 때 사용했습니다.약속, 매핑 또는 for-of-loop은 사용하지 않습니다.

// n'th triangular number recursion (aka factorial addition)
function triangularNumber(n) {
    if (n <= 1) {
        return n
    } else {
        return n + triangularNumber(n-1)
    }
}

// Example function that waits for each forEach() iteraction to complete
function testFunction() {
    // Example array with values 0 to USER_INPUT
    var USER_INPUT = 100;
    var EXAMPLE_ARRAY = Array.apply(null, {length: USER_INPUT}).map(Number.call, Number) // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, n_final... ] where n_final = USER_INPUT-1

    // Actual function used with whatever actual array you have
    var arrayLength = EXAMPLE_ARRAY.length
    var countMax = triangularNumber(arrayLength);
    var counter = 0;
    EXAMPLE_ARRAY.forEach(function(entry, index) {
        console.log(index+1); // show index for example (which can sometimes return asynchrounous results)

        counter += 1;
        if (triangularNumber(counter) == countMax) {

            // function called after forEach() is complete here
            completionFunction();
        } else {
            // example just to print counting values when max not reached
            // else would typically be excluded
            console.log("Counter index: "+counter);
            console.log("Count value: "+triangularNumber(counter));
            console.log("Count max: "+countMax);
        }
    });
}
testFunction();

function completionFunction() {
    console.log("COUNT MAX REACHED");
}

저는 같은 문제에 대처해야 했습니다(각각 내부에서 여러 약속을 사용). 현재 제시된 해결 방법은 모두 저에게 도움이 되지 않았습니다.그래서 체크 어레이를 구현했습니다.각 약속의 상태가 모두 갱신되고 있습니까?우리는 그 과정을 마무리 짓는 일반적인 약속이 있다.우리는 각각의 약속이 완료되었을 때에만 일반적인 약속을 해결합니다.코드 조각:

function WaitForEachToResolve(fields){

    var checked_fields = new Array(fields.length).fill(0);
    const reducer = (accumulator, currentValue) => accumulator + currentValue;

    return new Promise((resolve, reject) => {

      Object.keys(fields).forEach((key, index, array) => {

        SomeAsyncFunc(key)
        .then((result) => {

            // some result post process

            checked_fields[index] = 1;
            if (checked_fields.reduce(reducer) === checked_fields.length)
                resolve();
        })
        .catch((err) => {
            reject(err);
        });
      }
    )}
}

.then() 구문 대신 async-ait를 사용하고 싶기 때문에 데이터의 비동기 처리를 위해 @Ronaldo의 답변을 다음과 같이 수정했습니다.

let finalData = [];
var bar = new Promise(resolve => {
    foo.forEach((value, index) => {
        const dataToGet = await abcService.getXyzData(value);
        finalData[index].someKey = dataToGet.thatOtherKey;
        // any other processing here
        if (finalData[dataToGet.length - 1].someKey) resolve();
    });
});

await Promise.all([bar]);
console.log(`finalData: ${finalData}`);

메모: 조건을 충족시키겠다는 약속이 해결되는 if 조건을 수정했습니다. 당신의 경우에도 똑같이 할 수 있습니다.

비동기/라고 기능을 사용하고 할 수 .이거는 비동기/대기 기능을 사용하고 있기 때문입니다.forEach루프 안에서 당신만의 논리를 사용할 수 있어요

    let bar = new Promise((resolve, reject) => {
        snapshot.forEach(async (doc) => {
            """Write your own custom logic and can use async/await
            """
            const result = await something()
            resolve(result);
        });
    });
    let test = []
    test.push(bar)
    let concepts = await Promise.all(test);
    console.log(concepts);

간단한 비교 코드를 위해 문장으로 사용하는 것이 좋습니다.

doit();
function doit() {

        for (var i = 0; i < $('span').length;  i++) {
            console.log(i,$('span').eq(i).text() );
            if ( $('span').eq(i).text() == "Share a link to this question"  ) { //  span number 59
                return;
            }
        }

alert('never execute');

}

for을 사용하다

await players.reduce(async (a, player) => {
  // Wait for the previous item to finish processing
  await a;
  // Process this item
  await givePrizeToPlayer(player);
}, Promise.resolve());

https://gist.github.com/joeytwiddle/37d2085425c049629b80956d3c618971 를 참조해 주세요.

.forEach()

//count
var expecting = myArray.length;

myArray.forEach(function(item){

//do logic here
var item = item



//when iteration done
if (--expecting === 0) {

console.log('all done!');

}

})

언급URL : https://stackoverflow.com/questions/38406920/best-way-to-wait-for-foreach-to-complete

반응형