web-dev-qa-db-ja.com

より速いもの:キャッチ対プロミスを試してください

リソースが多くかかるので、try/catchの使用は一切避けた方がいいという意見を聞きました。では、promiseのエラー処理を高速化できますか?それともまったく関係ありませんか?

function f(somethingDangerous) {
  return new Promise((resolve, reject) => {
    // try {
    //   somethingDangerous();
    //   resolve();
    // } catch (err) {
    //   reject(err);
    // }

    // VS

    somethingDangerous();
    resolve();
  }).catch((err) => {
    console.error('Catched: ' + err);
  });
}

f(() => {throw 'DANGEROUS THING';});

[〜#〜] upd [〜#〜]:try/catchが内部の非同期コードで機能しないことはわかっています。パフォーマンスの問題のためにtry/catchを回避する理由があるのか​​と思っています。上記の2つのアプローチに違いはありますか?

UPD2:私の馬と競争しようとしました:) https://jsperf.com/try-catch-vs-promise

10
Alendorff

非同期関数にはPromises onlyを使用する必要があります。それらをエラーモナドとして乱用しないでください。これはリソースの無駄遣いであり、固有の非同期によりすべてが煩雑になります。

同期コードがある場合は、例外処理にtry/catchを使用します。

/* Wrong */
return new Promise(function(resolve, reject) {
    resolve(x / y);
}).catch(err => NaN)

/* Right */
try {
    return x / y;
} catch(e) {
    return NaN;
}

Iffすでにプロミスコードを持っているので、特定の状況でそれを回避できます。例外でプロミスを拒否したい場合。それらの場合、あなたはあなたの約束の組み込みエラー処理がその仕事をするのを任せるべきであり、追加のしかし無意味なtry/catchレイヤーによってすべてを複雑にしないでください:

/* Wrong */
new Promise(function(resolve, reject) {
    try { // when used synchronous in the executor callback
        …
        resolve(somethingSynchronous());
    } catch (e) {
        reject(e);
    }
});

/* Right */
new Promise(function(resolve, reject) {
    …
    resolve(somethingExceptionally());
});
/* Wrong */
….then(function(res) {
    try {
        …
        return somethingExceptionally();
    } catch(e) {
        return Promise.reject(e);
    }
}).…

/* Right */
….then(function(res) {
    …
    return somethingExceptionally();
}).…
16
Bergi

try/catchイディオムは、完全にsynchronousコードがある場合に非常にうまく機能しますが、asynchronous操作はそれを役に立たなくし、エラーがキャッチされません。つまり、外部スタックが実行され、エラーなしで最後の行に到達する間に、関数はそのコースを開始します。非同期関数内の将来のある時点でエラーが発生した場合、何も捕捉されません。

Promisesを使用すると、「エラー処理ができなくなりました」と言うかもしれません。そうです、ここではエラーを伝播するために特別なことをする必要はありません。なぜなら、Promiseを返し、エラーフローのサポートが組み込まれているからです。

2