Promiseのコールバックを非同期として定義しなければならないことに本質的に何か問題があるようです:
return new Promise(async (resolve, reject) => {
const value = await somethingAsynchronous();
if (value === something) {
return resolve('It worked!');
} else {
return reject('Nope. Try again.');
}
});
これは明らかに アンチパターン であり、コーディング それから発生する可能性のある問題 があります。 await
/try
ブロック内にcatch
ステートメントを配置した場合でも、ここでエラーを捕捉するのに失敗しやすくなることを理解しています。
私の最初の質問は、別の解決/拒否値でPromiseを転送したい場合、このようなものをコーディングするための最良の方法は何ですか? then/catch?つまり.
return new Promise((resolve, reject) => {
somethingAsynchronous().then(value => {
if (value === something) {
return resolve('It worked!');
} else {
return reject('Nope. Try again.');
}
}); // errors would now be propagated up
});
または、提案されているように、Promiseコンストラクターから完全に削除しますか here ?
async function outerFunction() {
const value = await somethingAsynchronous();
return new Promise((resolve, reject) => {
if (value === something) {
return resolve('It worked!');
} else {
return reject('Nope. Try again.');
}
});
}
しかし、outerFunction()に複数のawaitステートメントがある場合、つまり、複数の非同期関数を呼び出す線形コードブロックがある場合はどうでしょうか。その後、毎回新しいプロミスを作成して返す必要がありますか?
しかし、このようなコードをどのように説明しますか?
async function outerFunction() {
if (someSynchronousCheck()) {
return 'Nope. Try again.' // another reject case
}
const value = await somethingAsynchronous();
// ...
}
これを本来よりも複雑にしているような気がします。コールバックのネスト/ then/catchブロックのネストを避けて、今後問題が発生しないようにしています。
私の最後の質問は、Promiseに渡されるコールバックが本質的にasync
ではないのはなぜですか?これはすでにpromiseにラップされており、解決/拒否関数が非同期で呼び出されることを想定しています。
これをして:
async function outerFunction() {
const value = await somethingAsynchronous();
if (value === something) {
return 'It Worked!';
}
throw Error('Nope. Try again.');
}
async
を使用すると、outerFunction
の結果がPromiseでラップされます。
そのラッピングプロミスが何かに解決することを望む場合は、async
関数からそれを返すだけです。ラッピングプロミスを拒否する場合は、async
関数内でエラーをスローします。
しかし、このようなコードをどのように説明しますか?
async function outerFunction() {
if (someSynchronousCheck()) {
throw Error('Nope. Try again.');
}
const value = await somethingAsynchronous();
// ...
}
new Promise(async (resolve, reject) => { ... })
は比較的新しいアンチパターンです。その結果、1つではなく2つのpromiseオブジェクトが作成され、コンストラクター内で発生するキャッチされないエラーはtry..catch
でキャッチできず、処理されない拒否が発生します。
Promise非同期コードはasync..await
で処理できることを考えると、Promise
コンストラクターの現在の使用例は非promise非同期コードです。
new Promise(resolve => setTimeout(resolve, 1000))
Promise
コンストラクターに同期コードが含まれる場合、または他のpromiseが含まれる場合、promiseはasync
関数を使用して作成する必要があります。ドロップイン置換はasync
IIFEです。
return (async (resolve, reject) => {
const value = await somethingAsynchronous();
if (value === something) {
return 'It worked!';
} else {
throw 'Nope. Try again.';
}
})();
Promise
と一緒に使用するときにasync
コンストラクターの必要性が依然として存在する場合、Promise
コンストラクターを階層内で下に移動して、async
関数をラップしないようにする必要があります。
私の最後の質問は、Promiseに渡されるコールバックが本質的に非同期ではないのはなぜですか?これはすでにpromiseにラップされており、解決/拒否関数が非同期で呼び出されることを想定しています。
async
関数は、単に非同期に実行される関数ではなく、利用されることになっている別のpromiseを返します-または少なくともcatch
で処理されます。 Promise
は、関数の構築から返されるpromiseを利用するものではありません。
コンストラクターは同じティックで解決でき、必ずしも非同期である必要はありません。
Promise.resolve(1);
と類似しています
Promise(resolve => resolve(1))
そしてしない
Promise(resolve => setTimeout(() => resolve(1)))
これを行うだけで、自分でプロミスを連鎖させることもできます。
return new Promise(async (resolve, reject) => {
somethingAsynchronous().then((value) => {
if (value === something) {
return resolve('It worked!');
} else {
return reject('Nope. Try again.');
}
}, (error) => { reject(error); });
});
私はしばらくこれを使用してきましたが、それは私にとって完璧に機能します。