비동기 적으로 작업을 수행하는 메서드를 호출하는 루프가 있습니다. 이 루프는 메서드를 여러 번 호출 할 수 있습니다. 이 루프 이후에는 모든 비동기 작업이 완료 될 때만 실행해야하는 또 다른 루프가 있습니다.
그래서 이것은 내가 원하는 것을 보여줍니다.
for (i = 0; i < 5; i++) {
doSomeAsyncStuff();
}
for (i = 0; i < 5; i++) {
doSomeStuffOnlyWhenTheAsyncStuffIsFinish();
}
나는 약속에별로 익숙하지 않은데 누구든지 나를 도와 줄 수 있습니까?
이것이 내 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);
});
});
}
그러나 구문이 확실하지 않습니다.
답변
이를 위해 Promise.all
( spec , MDN )을 사용할 수 있습니다 . 여러 개의 개별 약속을 수락하고 사용자가 제공 한 모든 약속이 해결 될 때 해결되는 단일 약속을 돌려주고 그중 하나가 거부되면 거부됩니다.
따라서 doSomeAsyncStuff
약속 을 반환하면 :
const promises = [];
// ^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−− use `const` or `let`, not `var`
for (let i = 0; i < 5; i++) {
// ^^^−−−−−−−−−−−−−−−−−−−−−−−− added missing declaration
promises.push(doSomeAsyncStuff());
}
Promise.all(promises)
.then(() => {
for (let i = 0; i < 5; i++) {
// ^^^−−−−−−−−−−−−−−−− added missing declaration
doSomeStuffOnlyWhenTheAsyncStuffIsFinish();
}
})
.catch((e) => {
// handle errors here
});
MDN에는 여기 에 약속에 대한 기사가 있습니다 . 또한 제 책 JavaScript : The New Toys의 8 장에서 프록시에 대해 자세히 다룹니다 .
예를 들면 다음과 같습니다.
function doSomethingAsync(value) {
return new Promise((resolve) => {
setTimeout(() => {
console.log("Resolving " + value);
resolve(value);
}, Math.floor(Math.random() * 1000));
});
}
function test() {
const promises = [];
for (let 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();
샘플 출력 (으로 인해 Math.random
먼저 완료되는 내용이 다를 수 있음) :
해결 3 해결 2 해결 1 해결 4 0 해결 모두 완료 [0,1,2,3,4]
답변
재사용 가능한 함수는이 패턴에 대해 잘 작동합니다.
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));
답변
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)),
]);
답변
여기에 명시된 답변을 이해하기 위해 내가 작성한 코드가 있습니다. for 루프에 몽구스 쿼리가 있으므로 여기에을 넣어 asyncFunction
대신합니다. 누구에게나 도움이되기를 바랍니다. 이 스크립트는 노드 또는 여러 Javascript 런타임에서 실행할 수 있습니다.
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!");
}
)
답변
/*** 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