async / await構文で拒否する方法は?

320
Phoenix 2017-02-25 22:20.

async/await関数によって返されたpromiseを拒否するにはどうすればよいですか?

例:元々:

foo(id: string): Promise<A> {
  return new Promise((resolve, reject) => {
    someAsyncPromise().then((value)=>resolve(200)).catch((err)=>reject(400))
  });
}

async/に翻訳await

async foo(id: string): Promise<A> {
  try{
    await someAsyncPromise();
    return 200;
  } catch(error) {//here goes if someAsyncPromise() rejected}
    return 400; //this will result in a resolved promise.
  });
}

では、この場合、どうすればこの約束を適切に拒否できますか?

7 answers

374
T.J. Crowder 2017-02-25 22:23.

あなたの最善の策は、にあるラッピングと拒否約束して結果の値、ラッピング値:throwErrorError

} catch (error) {
    throw new Error(400);
}

throw値だけを指定することもできますが、スタックトレース情報はありません。

} catch (error) {
    throw 400;
}

または、Error値をラップして拒否されたプロミスを返しますが、慣用的ではありません。

} catch (error) {
    return Promise.reject(new Error(400));
}

(または単にreturn Promise.reject(400);、しかし繰り返しますが、コンテキスト情報はありません。)

あなたの場合、あなたが使用していてTypeScriptfooの戻り値がPromise<A>であるとき、あなたはこれを使うでしょう:

return Promise.reject<A>(400 /*or Error*/ );

ではasync/のawait状況、その最後はおそらくセマンティック不一致のビットですが、それは作業を行います。

をスローするとError、構文でfooの結果を消費するものとうまく機能しawaitます。

try {
    await foo();
} catch (error) {
    // Here, `error` would be an `Error` (with stack trace, etc.).
    // Whereas if you used `throw 400`, it would just be `400`.
}
155
David 2017-10-12 23:48.

catch()内部的にはまだpromiseが返されるため、非同期操作の呼び出し後に関数を単純にチェーンできることにも言及する必要があります。

await foo().catch(error => console.log(error));

このようにして、try/catch構文が気に入らない場合は構文を回避できます。

12
Andrew 2018-02-09 13:20.

promiseを受け取り、エラーがない場合はデータを含む配列を返し、エラーがあった場合はエラーを返すラッパー関数を作成できます。

function safePromise(promise) {
  return promise.then(data => [ data ]).catch(error => [ null, error ]);
}

ES7および非同期関数では次のように使用します。

async function checkItem() {
  const [ item, error ] = await safePromise(getItem(id));
  if (error) { return null; } // handle error and return
  return item; // no error so safe to use item
}
9
OzzyTheGiant 2017-12-28 06:51.

非同期関数を作成するためのより良い方法は、保留中のPromiseを最初から返し、拒否されたPromiseをエラーで吐き出すのではなく、Promiseのコールバック内で拒否と解決の両方を処理することです。例:

async foo(id: string): Promise<A> {
    return new Promise(function(resolve, reject) {
        // execute some code here
        if (success) { // let's say this is a boolean value from line above
            return resolve(success);
        } else {
            return reject(error); // this can be anything, preferably an Error object to catch the stacktrace from this function
        }
    });
}

次に、返されたpromiseでメソッドをチェーンします。

async function bar () {
    try {
        var result = await foo("someID")
        // use the result here
    } catch (error) {
        // handle error here
    }
}

bar()

ソース-このチュートリアル:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

5
unional 2017-02-25 22:37.

これは@TJクラウダーの答えではありません。「実際、例外が拒否に変換される場合、それがエラーであるかどうかが実際に気になるかどうかはわかりません。エラーのみをスローする理由はおそらく当てはまりません。 「」

コードでasync/を使用している場合awaitでも、:のError代わりに/を使用して拒否することをお勧めし400ます。

try {
  await foo('a');
}
catch (e) {
  // you would still want `e` to be an `Error` instead of `400`
}
5
Pedro Lourenço 2018-12-09 20:14.

複数のtry-catchブロックを使用せずに、新しいアプローチで拒否を適切に処理することを提案します。

import to from './to';

async foo(id: string): Promise<A> {
    let err, result;
    [err, result] = await to(someAsyncPromise()); // notice the to() here
    if (err) {
        return 400;
    }
    return 200;
}

どこto.tsの機能をからインポートする必要があります。

export default function to(promise: Promise<any>): Promise<any> {
    return promise.then(data => {
        return [null, data];
    }).catch(err => [err]);
}

クレジットは次のリンクのDimaGrossmanに送られます。

3
RiqueW 2018-10-31 20:32.

私はこれが古い質問であることを知っていますが、私はスレッドに出くわしました、そしてここでエラーと拒否の間に矛盾があり、例外処理を使用しないように頻繁に繰り返されるアドバイスに反するようです(少なくとも多くの場合)予想されるケースに対処します。説明のために:非同期メソッドがユーザーを認証しようとして認証が失敗した場合、それは拒否(2つの予想されるケースの1つ)であり、エラー(たとえば、認証APIが利用できなかった場合)ではありません。

髪の毛を分割するだけではないことを確認するために、次のコードを使用して、3つの異なるアプローチのパフォーマンステストを実行しました。

const iterations = 100000;

function getSwitch() {
  return Math.round(Math.random()) === 1;
}

function doSomething(value) {
  return 'something done to ' + value.toString();
}

let processWithThrow = function () {
  if (getSwitch()) {
    throw new Error('foo');
  }
};

let processWithReturn = function () {
  if (getSwitch()) {
    return new Error('bar');
  } else {
    return {}
  }
};

let processWithCustomObject = function () {
  if (getSwitch()) {
    return {type: 'rejection', message: 'quux'};
  } else {
    return {type: 'usable response', value: 'fnord'};
  }
};

function testTryCatch(limit) {
  for (let i = 0; i < limit; i++) {
    try {
      processWithThrow();
    } catch (e) {
      const dummyValue = doSomething(e);
    }
  }
}

function testReturnError(limit) {
  for (let i = 0; i < limit; i++) {
    const returnValue = processWithReturn();
    if (returnValue instanceof Error) {
      const dummyValue = doSomething(returnValue);
    }
  }
}

function testCustomObject(limit) {
  for (let i = 0; i < limit; i++) {
    const returnValue = processWithCustomObject();
    if (returnValue.type === 'rejection') {
      const dummyValue = doSomething(returnValue);
    }
  }
}

let start, end;
start = new Date();
testTryCatch(iterations);
end = new Date();
const interval_1 = end - start;
start = new Date();
testReturnError(iterations);
end = new Date();
const interval_2 = end - start;
start = new Date();
testCustomObject(iterations);
end = new Date();
const interval_3 = end - start;

console.log(`with try/catch: ${interval_1}ms; with returned Error: ${interval_2}ms; with custom object: ${interval_3}ms`);

Javascriptインタープリターに関する私の不確実性のためにそこにあるもののいくつかが含まれています(私は一度に1つのウサギの穴を降りるのが好きです)。たとえば、doSomething関数を含め、そのreturnをdummyValueに割り当てて、条件付きブロックが最適化されないようにしました。

私の結果は次のとおりです。

with try/catch: 507ms; with returned Error: 260ms; with custom object: 5ms

小さな最適化を探すのに苦労する価値がない場合がたくさんあることを私は知っていますが、大規模なシステムでは、これらのことが大きな累積的な違いを生む可能性があり、それはかなり厳しい比較です。

だから…受け入れられた答えのアプローチは、非同期関数内で予測できないエラーを処理する必要があると予想される場合、拒否が単に「プランBを使用する必要がある(またはC、またはD…)」私の好みは、カスタム応答オブジェクトの使用を拒否することだと思います。

Related questions

MORE COOL STUFF

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは、夫に会ったとき、典型的な交際のアドバイスに逆らいました。

マイケルシーンが非営利の俳優である理由

マイケルシーンが非営利の俳優である理由

マイケルシーンは非営利の俳優ですが、それは正確にはどういう意味ですか?

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。

「たどりつけば」をオンラインでストリーミングできない理由

「たどりつけば」をオンラインでストリーミングできない理由

ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

サロンからのヘアトリミングや個人的な寄付は、油流出を吸収して環境を保護するのに役立つマットとして再利用できます。

ホワイトハウスの最も記憶に残る結婚式を見てください

ホワイトハウスの最も記憶に残る結婚式を見てください

過去200年以上の間にホワイトハウスで結婚したのはほんの数人です。彼らは誰でしたか、そしてそこで結婚式を獲得するために何が必要ですか?

Netflixのジョエルマクヘイルとのジョエルマクヘイルショーは、ジョエルマクヘイルにぴったりの車を復活させます

Netflixのジョエルマクヘイルとのジョエルマクヘイルショーは、ジョエルマクヘイルにぴったりの車を復活させます

ジョエル・マクヘイル、マイク・コルター(スクリーンショット:Netflix)「私の神よ、これは1つのことを変えます。」これは、ジョエル・マクヘイルとのジョエル・マクヘイルショーの最後のジョークです。リアリティ番組の嘲笑と寛大なスナキネスの時間は、なじみのある顔を見つけます。

チームロケットは20年ぶりにポケモンシリーズでアッシュを破った

チームロケットは20年ぶりにポケモンシリーズでアッシュを破った

画像経由:@pancakeparadox(Twitter)。1997年にポケモンシリーズが初公開されて以来、チームロケット(またはラテンアメリカではチームロケット)として知られる悪役のグループは、何度もアッシュに直面してきました。

今週の科学技術でトランプがめちゃくちゃになったことすべて

今週の科学技術でトランプがめちゃくちゃになったことすべて

画像:ゲッティ私たち全員が千年もの間生きていて、私たちの体が燃える風によってほこりと長引く悲鳴だけに押し流されたと考えるのは驚くべきことです。私たちがそうしていないことを除いて、それはトランプ政権の最初の週の終わりであり、驚くほど多くの恐ろしいことがすでに起こっています。

あなたの「マイクロピッグ」が代わりに通常のピッグになってしまったとしても驚かないでください

あなたの「マイクロピッグ」が代わりに通常のピッグになってしまったとしても驚かないでください

そして今、あることを手に入れていると思っていたが、まったく別のことをしてしまった男の話。CBSニュースは、彼女が「ミニブタ」であるという誤ったふりをしてエスターを養子にしたカナダ人のスティーブジェンキンスの心温まる物語をもたらします。これは、特にせいぜいゴールデンレトリバーまたはセントバーナードをストラップします。

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、生後4か月の娘、モナコに母乳育児をしていると語った。

Come diventare Web Developer?

Come diventare Web Developer?

Vorresti diventare web developer e non sai da dove cominciare?! Qui troverai tutte le risposte necessarie, anche io non sapevo che strada intraprendere ma voglio aiutarti a non commettere i miei stessi errori. Cosa imparare? Le competenza essenziali per qualsiasi web developer sono almeno tre.

投資ノート:Bioscout AU$300万シード

投資ノート:Bioscout AU$300万シード

Bioscoutは、農家を運転席に置くという使命を負っています。Artesian(GrainInnovate)やUniseedと並んで、最新のシードラウンドでチームを支援できることをうれしく思います。問題真菌症による重大な作物の損失は、農民にとって試練であることが証明されています。

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

遠隔医療は、パンデミック後の時代では新しいものではなく、時代遅れの分野でもありません。しかし、業界を詳しく見ると、需要と供給の強力な持続可能性と、米国で絶え間ない革命となる強力な潜在的成長曲線を示しています。

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

2021年は、世界的なベンチャーキャピタル(VC)の資金調達にとって記録的な年でした。DealStreetAsiaによると、東南アジアも例外ではなく、この地域では年間で記録的な25の新しいユニコーンが採掘されました。

Language