30
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

複数の非同期処理を実行して結果待つ

Last updated at Posted at 2018-01-19

今更ですがasync.jsのasync parallelをasync.jsを使わないでやるにはどうしたら良いのか疑問に思ったので試してみました。

Promise

  • try-catchでは同期処理例外しかキャッチできない。(Promiseをtry-catchで囲ってもPromise内部の例外はキャッチできません)
  • Promise内部で例外(throw new Error())が発生した場合には、それをrejectとして処理をします。(Promise内で発生した例外は、thenの第二引数、もしくはcatchで取得することが出来ます。)
  • thenやcatch内で例外(throw new Error())が起きた場合は、暗黙的にrejectとみなされる。
  • thenやcatchがPromise以外を返している場合は、暗黙的にPromise.resolveとみなされる。(thenの第一引数で取得できるが、catchはできない)

Promiseの結果を返すにはPromiseのresolveもしくはrejectを実行する。
thenはPromiseの結果を受けて実行されます。

async/await

  • async functionは呼び出されるとPromiseを返す。
  • async functionが値をreturnした場合、Promiseはその値をresolveする。
  • async functionがエラーや何らかの値をthrowした場合はその値をrejectする。
  • async functionは、await式を含むことできます。await式は、async関数の実行を一時停止し、await式のPromiseの解決を待つ。(値がPromiseではなかった場合は値を解決されたPromiseに変換して、それを待ちます。Promiseが拒否された場合、理由となった値をスローします。)
  • async function内のtry-catchではPromise内部で起きた非同期処理例外もキャッチできる。

動作確認

Promise エラーなし

const p1 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("one")}, 2000); 
}); 
const p2 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("two")}, 1000); 
});

Promise.all([p1, p2]).then(results => { 
    console.log(results);
}).catch(reject => { 
    console.log(reject);
});

// ["one", "two"]

Promise エラーあり

const p1 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("one")}, 2000); 
}); 
const p2 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("two")}, 1000); 
});
const p3 = new Promise((resolve, reject) => {
    reject("reject message");
});

Promise.all([p1, p2, p3]).then(results => { 
    console.log(results);
}).catch(reject => { 
    console.log(reject);
});

// reject message

async/await エラーなし

async function one() {
    return "one";
}
async function two() { 
    return "two";
}

Promise.all([one(), two()]).then(results => { 
    console.log(results);
}).catch(reject => { 
    console.log(reject);
});

// ["one", "two"]

async/await エラーあり

async function one() {
    return "one";
}
async function two() { 
    return "two";
}
async function three() { 
    throw "reject message";
}

Promise.all([one(), two(), three()]).then(results => { 
    console.log(results);
}).catch(reject => { 
    console.log(reject);
});

// reject message

補足

配列内のものは全てがPromiseである必要もありません。

const p1 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("one")}, 2000); 
}); 
const p2 = new Promise((resolve, reject) => { 
    setTimeout(() => {resolve("two")}, 1000); 
});

Promise.all([p1, p2, 3, "4"]).then(results => { 
    console.log(results);
}).catch(reject => { 
    console.log(reject);
});

// ["one", "two", 3, "4"]

thenのcatchのところは以下でも問題ないです。

Promise.all(配列).then(results => { 
    console.log(results)
}, reject => { 
    console.log(reject);
});
  • Promise.allはawaitでも待てる
await Promise.all([p1, p2, p3]);

これは全てが解決されるもしくは1つでも拒否されたら即座に返す。

全てのPromiseの結果関係なしに全てを完了を待つ場合は以下を使います。

await Promise.allSettled([p1, p2, p3]);
30
27
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?