IT박스

가져 오기 : JSON 오류 객체로 약속 거부

itboxs 2020. 12. 29. 06:51
반응형

가져 오기 : JSON 오류 객체로 약속 거부


성공과 실패 모두에 JSON 데이터를 반환하는 HTTP API가 있습니다.

실패의 예는 다음과 같습니다.

~ ◆ 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
   }

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

글쎄, resp.json약속 성취 것이고, 단지 Promise.reject그것을 기다리지 않고 약속으로 즉시 거부 할 뿐입니다 .

차라리 다음 작업을 원한다고 가정합니다.

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;});

response.ok에서 Promise반환하는 대신 기본 JSON 데이터 에 의존 하고 사용 하는 다소 깔끔한 접근 방식이 .json()있습니다.

function myFetchWrapper(url) {
  return fetch(url).then(response => {
    return response.json().then(json => {
      return response.ok ? json : Promise.reject(json);
    });
  });
}

// This should trigger the .then() with the JSON response,
// since the response is an HTTP 200.
myFetchWrapper('http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY').then(console.log.bind(console));

// This should trigger the .catch() with the JSON response,
// since the response is an HTTP 400.
myFetchWrapper('https://content.googleapis.com/youtube/v3/search').catch(console.warn.bind(console));


위의 Jeff Posnick 의 솔루션 은 제가 가장 좋아하는 방법이지만 중첩은 매우 추합니다.

With the newer async/await syntax we can do it in a more synchronous looking way, without the ugly nesting that can quickly become confusing.

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

This works because, an async function always returns a promise and once we have the JSON we can then decide how to return it based on the response status (using response.ok).

You would error handle the same way as you would in Jeff's answer, or you could use try/catch, or even an 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);
}

Also worth reading MDN - Checking that the fetch was successful for why we have to do this, essentially a fetch request only rejects with network errors, getting a 404 is not a network error.

ReferenceURL : https://stackoverflow.com/questions/29473426/fetch-reject-promise-with-json-error-object

반응형