Node.js 고유의 Promise.all 처리가 병렬 또는 순차적입니까?
문서 가 명확하지 않기 때문에이 점을 분명히하고 싶습니다 .
Q1은 : 되어 Promise.all(iterable)
순차적으로 또는 병렬로 모두 약속 처리? 더 구체적으로 말하자면, 체인 약속을 실행하는 것과 같습니다.
p1.then(p2).then(p3).then(p4).then(p5)....
또는 모든 알고리즘의 몇 가지 다른 종류의 p1
, p2
, p3
, p4
, p5
, 등 (병렬) 같은 시간에 호출되는 결과가 모두 해결 (또는 거부) 즉시 반환됩니다?
Q2 : 경우 Promise.all
병렬 실행, 반복 가능 sequencially을 실행하는 편리한 방법은 무엇입니까?
참고 : Q 또는 Bluebird를 사용하고 싶지 않지만 모든 기본 ES6 사양을 사용하고 싶습니다.
되어
Promise.all(iterable)
모든 약속을 실행?
아니요, 약속은 "실행"될 수 없습니다. 그들이 될 때 그들은 그들의 작업을 시작 만들어 그들은 단지 결과를 나타냅니다 - - 그리고 당신은 심지어에게 전달하기 전에 병렬로 모든 것을 실행하고 있습니다 Promise.all
.
Promise.all
단지 않습니다 await를 여러 약속을. 어떤 순서로 해결되는지 또는 계산이 병렬로 실행되는지는 중요하지 않습니다.
iterable을 순차적으로 실행하는 편리한 방법이 있습니까?
이미 약속이 있다면 많은 것을 할 수 없지만 Promise.all([p1, p2, p3, …])
(시퀀스 개념은 없습니다). 그러나 반복 가능한 비동기 함수가 있으면 실제로 순차적으로 실행할 수 있습니다. 기본적으로 당신은에서 얻을 필요가
[fn1, fn2, fn3, …]
에
fn1().then(fn2).then(fn3).then(…)
그리고 그 해결책은 다음을 사용하는 것입니다 Array::reduce
.
iterable.reduce((p, fn) => p.then(fn), Promise.resolve())
병행하여
await Promise.all(items.map(async item => { await fetchItem(item) }))
장점 : 더 빠릅니다. 하나라도 실패하더라도 모든 반복이 실행됩니다.
순서대로
for (let i = 0; i < items.length; i++) {
await fetchItem(items[i])
}
장점 : 루프의 변수는 각 반복마다 공유 할 수 있습니다. 일반적인 명령형 동기 코드처럼 동작합니다.
Bergis는 Array.reduce를 사용하여 올바른 길을 찾았습니다.
그러나 실제로 함수를 차례대로 실행하라는 약속을 반환하는 함수를 얻으려면 중첩을 더 추가해야했습니다.
내 실제 사용 사례는 다운 스트림 한계로 인해 차례로 순서대로 전송 해야하는 파일 배열입니다 ...
여기 내가 끝내는 것이 있습니다.
getAllFiles().then( (files) => {
return files.reduce((p, theFile) => {
return p.then(() => {
return transferFile(theFile); //function returns a promise
});
}, Promise.resolve()).then(()=>{
console.log("All files transferred");
});
}).catch((error)=>{
console.log(error);
});
이전 답변에서 제안했듯이 다음을 사용하십시오.
getAllFiles().then( (files) => {
return files.reduce((p, theFile) => {
return p.then(transferFile(theFile));
}, Promise.resolve()).then(()=>{
console.log("All files transferred");
});
}).catch((error)=>{
console.log(error);
});
다른 파일을 시작하기 전에 전송이 완료 될 때까지 기다리지 않았으며 첫 번째 파일 전송이 시작되기 전에 "전송 된 모든 파일"텍스트도 표시되었습니다.
내가 뭘 잘못했는지 모르지만 나를 위해 일한 것을 나누고 싶었습니다.
편집 :이 게시물을 작성한 이후로 첫 번째 버전이 작동하지 않는 이유를 이해했습니다. then () 은 약속을 반환하는 함수를 기대합니다 . 따라서 괄호없이 함수 이름을 전달해야합니다! 이제 내 함수는 인수를 원하므로 인수를 사용하지 않는 익명 함수로 감싸 야합니다!
@ Bergi의 대답을 자세히 설명하기 위해 (매우 간결하지만 이해하기 까다로운;)
이 코드는 배열의 각 항목을 실행하고 다음 '다음 체인'을 끝에 추가합니다.
function eachorder(prev,order) {
return prev.then(function() {
return get_order(order)
.then(check_order)
.then(update_order);
});
}
orderArray.reduce(eachorder,Promise.resolve());
이해가 되길 바랍니다.
재귀 함수를 사용하여 비동기 함수를 사용하여 반복 가능한 iterable을 순차적으로 처리 할 수도 있습니다. 예를 들어 a
비동기 함수로 처리 할 배열 이 주어지면 someAsyncFunction()
:
var a = [1, 2, 3, 4, 5, 6]
function someAsyncFunction(n) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("someAsyncFunction: ", n)
resolve(n)
}, Math.random() * 1500)
})
}
//You can run each array sequentially with:
function sequential(arr, index = 0) {
if (index >= arr.length) return Promise.resolve()
return someAsyncFunction(arr[index])
.then(r => {
console.log("got value: ", r)
return sequential(arr, index + 1)
})
}
sequential(a).then(() => console.log("done"))
Bergi's answer helped me to make the call synchronous.I have added an example below where we call each function after the previous function is called.
function func1 (param1) {
console.log("function1 : " + param1);
}
function func2 () {
console.log("function2");
}
function func3 (param2, param3) {
console.log("function3 : " + param2 + ", " + param3);
}
function func4 (param4) {
console.log("function4 : " + param4);
}
param4 = "Kate";
//adding 3 functions to array
a=[
()=>func1("Hi"),
()=>func2(),
()=>func3("Lindsay",param4)
];
//adding 4th function
a.push(()=>func4("dad"));
//below does func1().then(func2).then(func3).then(func4)
a.reduce((p, fn) => p.then(fn), Promise.resolve());
You can do it by for loop.
async function return promise
async function createClient(client) {
return await Client.create(client);
}
let clients = [client1, client2, client3];
if you write following code then client are created parallelly
const createdClientsArray = yield Promise.all(clients.map((client) =>
createClient(client);
));
then all clients are created parallelly. but if you want to create client sequentially then you should use for loop
const createdClientsArray = [];
for(let i = 0; i < clients.length; i++) {
const createdClient = yield createClient(clients[i]);
createdClientsArray.push(createdClient);
}
then all clients are created sequentially.
happy coding :)
I've been using for of in order to solve sequential promises. I'm not sure if it helps here but this is what I've been doing.
async function run() {
for (let val of arr) {
const res = await someQuery(val)
console.log(val)
}
}
run().then().catch()
this might answer part of your question.
yes, you can chain an array of promise returning functions as follows... (this passes the result of each function to the next). you could of course edit it to pass the same argument (or no arguments) to each function.
function tester1(a) {
return new Promise(function(done) {
setTimeout(function() {
done(a + 1);
}, 1000);
})
}
function tester2(a) {
return new Promise(function(done) {
setTimeout(function() {
done(a * 5);
}, 1000);
})
}
function promise_chain(args, list, results) {
return new Promise(function(done, errs) {
var fn = list.shift();
if (results === undefined) results = [];
if (typeof fn === 'function') {
fn(args).then(function(result) {
results.push(result);
console.log(result);
promise_chain(result, list, results).then(done);
}, errs);
} else {
done(results);
}
});
}
promise_chain(0, [tester1, tester2, tester1, tester2, tester2]).then(console.log.bind(console), console.error.bind(console));
Using async await an array of promises can easily be executed sequentially:
let a = [promise1, promise2, promise3];
async function func() {
for(let i=0; i<a.length; i++){
await a[i]();
}
}
func();
Note: In above implementation, if a promise is rejected, the rest wouldn't be executed.If you want all your promises to be executed, then wrap your await a[i]();
inside try catch
'Programming' 카테고리의 다른 글
Bash에서 변수에 출력 할당 (0) | 2020.06.15 |
---|---|
더 이상 사용되지 않는 -sizeWithFont : constrainedToSize : lineBreakMode :를 iOS 7에서 대체 하시겠습니까? (0) | 2020.06.15 |
'C'에서 색인이 0으로 시작되는 이유는 무엇입니까? (0) | 2020.06.15 |
추적되지 않은 파일 만 추가 (0) | 2020.06.15 |
문자열에서 큰 따옴표를 이스케이프 처리 (0) | 2020.06.15 |