fetch:使用JSON错误对象拒绝承诺

时间:2015-04-06 14:38:56

标签: javascript promise es6-promise fetch-api

我有一个HTTP API,可以在成功和失败时返回JSON数据。

示例失败将如下所示:

~ ◆ http get http://localhost:5000/api/isbn/2266202022 
HTTP/1.1 400 BAD REQUEST
Content-Length: 171
Content-Type: application/json
Server: TornadoServer/4.0

{
    "message": "There was an issue with at least some of the supplied values.", 
    "payload": {
        "isbn": "Could not find match for ISBN."
    }, 
    "type": "validation"
}

我想在JavaScript代码中实现的目标是这样的:

fetch(url)
  .then((resp) => {
     if (resp.status >= 200 && resp.status < 300) {
       return resp.json();
     } else {
       // This does not work, since the Promise returned by `json()` is never fulfilled
       return Promise.reject(resp.json());
     }
   })
   .catch((error) => {
     // Do something with the error object
   }

2 个答案:

答案 0 :(得分:85)

 // This does not work, since the Promise returned by `json()` is never fulfilled
return Promise.reject(resp.json());

嗯,resp.json承诺完成,只有Promise.reject不会等待它,并立即拒绝带有承诺的 。< / p>

我假设你想要做以下事情:

fetch(url).then((resp) => {
  let json = resp.json(); // there's always a body
  if (resp.status >= 200 && resp.status < 300) {
    return json;
  } else {
    return json.then(Promise.reject.bind(Promise));
  }
})

(或明确写明)

    return json.then(err => {throw err;});

答案 1 :(得分:4)

上面Jeff Posnick的解决方案是我最喜欢的方式,但嵌套非常难看。

使用较新的 async / await 语法,我们可以采用更加同步的方式进行,而不会使丑陋的嵌套很快变得混乱。

async function myFetchWrapper(url) {
  const response = await fetch(url);
  const json = await response.json();
  return response.ok ? json : Promise.reject(json);
}

这是有效的,因为an async function always returns a promise,一旦我们有了JSON,我们就可以决定如何根据响应状态返回它(使用response.ok)。

您的错误处理方式与Jeff的答案相同,或者您可以使用try / catch,甚至是error handling higher order function

const url = 'http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY'

// Example with Promises
myFetchWrapper(url)
  .then((res) => ...)
  .catch((err) => ...);

// Example with try/catch (presuming wrapped in an async function)
try {
  const data = await myFetchWrapper(url);
  ...
} catch (err) {
  throw new Error(err.message);
}

另外值得一读MDN - Checking that the fetch was successful为什么我们必须这样做,本质上一个获取请求只拒绝网络错误,获得404不是网络错误。