2017-01-18 10 views
1

フェッチ内で500の内部サーバーエラーを処理しようとしています。内部エラーが発生した場合、サーバーはメッセージで応答します。私はそのメッセージを抽出したい。fetch約束 - 内部サーバーエラーを返す

const req = new Request(url, { 
     method: node.method, 
     mode: 'cors', 
     headers: { 'Content-Type': 'application/json' }, 
     body: JSON.stringify(body), 
    }); 
    fetch(req) 
     .then((response) => { 
     if (response.status === 500) { 
      // res.json extracts the body from the response as a promise, chain 
      // .then on it and throw an error to be caught in the lower catch. 
      response.json() 
      .then((json) => { 
      const { message, stackTrace } = json; 
      throw new ServerException(message, stackTrace); // note 1 
      }) 
      .catch((error) => { 
      return Promise.reject(RawException(error)); // note 2 
      }); 
     } else { 
      return response.json(); 
     } 
     }) 
     .then((json) => { // note 3 
     dispatch(stopLoading()); 
     dispatch(recieveResponse(typeOfRequest, json)); 
     }) 
     .catch((e) => { 
     dispatch(stopLoading()); 
     dispatch(responseError()); 
     dispatch(showError(e.message)); 
     }); 
    }; 

私の問題は、応答の本文を抽出することは、新たな約束を作成することです、と私は内側の1から外側の約束を拒否することができません。

注1は内側の約束のcatchメソッドをトリガーします。キャッチ内で、私は別のエラーを投げてみましたが、うまくいかないようです。 2番目の行にI throw new RawException(error)がある場合、何も起こらず、3番目に注目した行のthenメソッドがトリガされます。私が提供したコードのように私が拒否された約束を返せば、引き続き引き金が引けますが、jsonは未定義です。

どうすればよいですか?

+1

最初の 'response.json()'を '返す 'という問題はありませんか? 'response.status === 500'の場合は、実際には何も返されません。しかし、あなたは 'return response.json(); 'であなたの他にいます。 – zero298

+0

@ zero298によるが、500エラー処理でreturn return.json()。then(...)としてリターンを挿入した後は、拒否された約束を返すために直後の.catch句は必要ありません。その約束は「スロー」によって拒否されます。 – traktor53

+0

@ JaromandaX私は、OPのオブザーバ「注1がインナーキャッチメソッドをトリガする」に基づいてコメントを書いた。あなたが指摘しているように、これは常に正しいとは限りません。まれにも真実ではないかもしれません。訂正してくれてありがとう。 – traktor53

答えて

4

解決策は、約束を入れ子にするのではなく、外側の約束の.thenを解決/返すことです。

if (response.status === 500) { 
    response.json() // response.json returns a promise, we chose to do nothing with its 
    .then((json) => { // conclusion 
    const { message, stackTrace } = json; 
    throw new ServerException(message, stackTrace); // note 1 
    }) 
    .catch((error) => { 
    return Promise.reject(RawException(error)); // note 2 
    }); 
} else { 
    return response.json(); 
} 

は、その構文が好まれている場合、他の句は同様に除去することができ

if (response.status === 500) { 
    return response.json() // return the result of the inner promise, which is an error 
    .then((json) => { 
    const { message, stackTrace } = json; 
    throw new ServerException(message, stackTrace); 
    }); 
} else { 
    return response.json(); 
} 

になるはずです。 ESLintはelseが無駄であると不平を言っていますが、コードの分岐を明示的にする方法は間違いありません。

+0

はい、これです。サーバー例外を再ラップするのではなく、 'json()'から生の例外をラップする場合は、 '.then(({message、stackTrace})=> {throw new ServerException(message、stackTrace) ;}}、エラー=> {新しいRawExceptionをスロー(エラー);}) '。相違点についてはこちらを参照してください(http://stackoverflow.com/q/24662289/1048572)。 – Bergi