programing

가져오기: 상태가 정상이 아닐 경우 약속을 거부하고 오류를 잡습니까?

cafebook 2023. 10. 5. 23:31
반응형

가져오기: 상태가 정상이 아닐 경우 약속을 거부하고 오류를 잡습니까?

제가 할 일은 이렇습니다.

import 'whatwg-fetch';

function fetchVehicle(id) {
    return dispatch => {
        return dispatch({
            type: 'FETCH_VEHICLE',
            payload: fetch(`http://swapi.co/api/vehicles/${id}/`)
                .then(status)
                .then(res => res.json())            
                .catch(error => {
                    throw(error);
                })
            });
    };
}

function status(res) {
    if (!res.ok) {
        return Promise.reject()
    }
    return res;
}

편집: 그 약속은 거절당하지 않습니다. 그것이 제가 이해하려는 것입니다.

리덕스에서 이 페치 폴리필을 리덕스 약속 미들웨어와 함께 사용하고 있습니다.

가져오기 약속은 네트워크 오류가 발생할 때만 TypeError와 함께 거부합니다.4xx와 5xx 응답은 네트워크 오류가 아니기 때문에 잡을 것이 없습니다.사용하려면 직접 오류를 던져야 합니다.Promise#catch.

fetch Response는 요청이 성공했는지 여부를 알려주는 를 편리하게 제공합니다.이와 같은 것이 효과가 있을 것입니다.

fetch(url).then((response) => {
  if (response.ok) {
    return response.json();
  }
  throw new Error('Something went wrong');
})
.then((responseJson) => {
  // Do something with the response
})
.catch((error) => {
  console.log(error)
});

다음의login with username and password예제에서는 다음을 수행하는 방법을 보여 줍니다.

  1. 확인.response.ok
  2. reject문제가 없다면 오류를 던지는 대신
  3. 검증 문제와 같은 서버의 오류 힌트를 추가로 처리합니다.
login() {
  const url = "https://example.com/api/users/login";
  const headers = {
    Accept: "application/json",
    "Content-Type": "application/json",
  };
  fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify({
      email: this.username,
      password: this.password,
    }),
  })
    .then((response) => {
      // 1. check response.ok
      if (response.ok) {
        return response.json();
      }
      return Promise.reject(response); // 2. reject instead of throw
    })
    .then((json) => {
      // all good, token is ready
      this.store.commit("token", json.access_token);
    })
    .catch((response) => {
      console.log(response.status, response.statusText);
      // 3. get error messages, if any
      response.json().then((json: any) => {
        console.log(json);
      })
    });
},

모두 도와주셔서 감사합니다. 약속을 거부합니다..catch()내 문제 해결:

export function fetchVehicle(id) {
    return dispatch => {
        return dispatch({
            type: 'FETCH_VEHICLE',
            payload: fetch(`http://swapi.co/api/vehicles/${id}/`)
                .then(status)
                .then(res => res.json())    
                .catch(error => {
                    return Promise.reject()
                })
            });
    };
}


function status(res) {
    if (!res.ok) {
        throw new Error(res.statusText);
    }
    return res;
}

저는 fny 답변이 정말로 모든 것을 받았습니다. fetch는 오류를 던지는 것이 아니기 때문에 우리는 오류를 직접 던지거나 처리해야 합니다.내 솔루션을 비동기식/대기식으로 게시합니다.제 생각에는 좀 더 앞으로 다가가서 읽을 수 있는 것 같아요.

해결책 1: 오류를 던지는 것이 아니라, 오류를 우리가 직접 처리합니다.

  async _fetch(request) {
    const fetchResult = await fetch(request); //Making the req
    const result = await fetchResult.json(); // parsing the response

    if (fetchResult.ok) {
      return result; // return success object
    }


    const responseError = {
      type: 'Error',
      message: result.message || 'Something went wrong',
      data: result.data || '',
      code: result.code || '',
    };

    const error = new Error();
    error.info = responseError;

    return (error);
  }

여기서 오류가 발생하면 오류 객체인 일반 JS 객체를 만들고 반환하는 것인데, 문제는 외부에서 처리해야 한다는 것입니다.사용방법:

  const userSaved = await apiCall(data); // calling fetch
  if (userSaved instanceof Error) {
    debug.log('Failed saving user', userSaved); // handle error

    return;
  }
  debug.log('Success saving user', userSaved); // handle success

해결책 2: 오류 던지기, try/catch 사용하기

async _fetch(request) {
    const fetchResult = await fetch(request);
    const result = await fetchResult.json();

    if (fetchResult.ok) {
      return result;
    }

    const responseError = {
      type: 'Error',
      message: result.message || 'Something went wrong',
      data: result.data || '',
      code: result.code || '',
    };

    let error = new Error();
    error = { ...error, ...responseError };
    throw (error);
  }

Error Cector에서 문자열만 승인하므로 일반 Error js 개체를 생성하므로 다음과 같이 생성할 수 있습니다.

  try {
    const userSaved = await apiCall(data); // calling fetch
    debug.log('Success saving user', userSaved); // handle success
  } catch (e) {
    debug.log('Failed saving user', userSaved); // handle error
  }

해결책 3: 고객 오류 사용

  async _fetch(request) {
    const fetchResult = await fetch(request);
    const result = await fetchResult.json();

    if (fetchResult.ok) {
      return result;
    }

    throw new ClassError(result.message, result.data, result.code);
  }

그리고:

class ClassError extends Error {

  constructor(message = 'Something went wrong', data = '', code = '') {
    super();
    this.message = message;
    this.data = data;
    this.code = code;
  }

}

도움이 됐길 바랍니다.

2021 TypeScript Answer

제가 하는 일은 a를 쓰는 것입니다.fetch일반적인 것을 취하는 포장지 그리고 만일.responseok그것은 자동으로 될 것입니다..json()그리고 type assert 결과를 입력합니다. 그렇지 않으면 포장지는 다음을 던집니다.response

export const fetcher = async <T>(input: RequestInfo, init?: RequestInit) => {
  const response = await fetch(input, init);

  if (!response.ok) {
    throw response;
  }

  return response.json() as Promise<T>;
};

그리고 나서 오류를 잡아내고 그것들이 그들의 것인지 확인할 것입니다.instanceof Response. 그런 식으로 TypeScript는error가지다Response등의 속성status statusText body headers등과 나는 각각의 맞춤형 메시지를 적용할 수 있습니다.4xx 5xx상태 코드.

try {
  return await fetcher<LoginResponse>("http://localhost:8080/login", {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ email: "user@example.com", password: "passw0rd" }),
  });
} catch (error) {
  if (error instanceof Response) {
    switch (error.status) {
      case 401:
        throw new Error("Invalid login credentials");
      /* ... */
      default:
        throw new Error(`Unknown server error occured: ${error.statusText}`);
    }
  }
  throw new Error(`Something went wrong: ${error.message || error}`);
}

만약 네트워크 에러와 같은 것이 발생한다면 그것은 외부에서 잡힐 수 있습니다.instanceof Response보다 일반적인 메시지로 확인합니다.

throw new Error(`Something went wrong: ${error.message || error}`);

@fny(받아들인 대답)라는 대답은 저에게 통하지 않았습니다.throw new Error()그들은 그들에게 납치당하지 않았습니다..catch. 내 해결책은 포장하는 것이었습니다.fetch새로운 약속을 구축하는 기능으로:


function my_fetch(url, args) {
  return new Promise((resolve, reject) => {
    fetch(url, args)
    .then((response) => {
      response.text().then((body) => { 
        if (response.ok) {
          resolve(body) 
        } else {
          reject(body) 
        }
      })
    })
    .catch((error) => { reject(error) })
  })
}

이지 않은 은 될 것입니다..catch방법:

my_fetch(url, args)
.then((response) => {
  // Do something with the response
})
.catch((error) => {
  // Do something with the error
})
function handleErrors(response) {
    if (!response.ok) {
        throw Error(response.statusText);
    }
    return response;
}
fetch("https://example.com/api/users")
    .then(handleErrors)
    .then(response => console.log("ok") )
    .catch(error => console.log(error) );

대부분의 답변에 공감을 주는 또 다른 (짧은) 버전:

fetch(url)
.then(response => response.ok ? response.json() : Promise.reject(response))
.then(json => doStuff(json)) //all good

//next line is optional
.catch(response => handleError(response)) //handle error

제안한 솔루션 중 어느 것도 만족스럽지 못하여 Fetch API로 성공 응답과 오류 응답을 모두 처리할 수 있는 방법을 찾아 보았습니다.

계획은 다음과 같습니다.{status: XXX, message: 'a message'}두 경우 모두 결과적으로 형식이 지정됩니다.

참고: 성공 응답에 빈 본문이 포함될 수 있습니다.그런 경우 우리는 뒤로 물러나서 사용합니다.Response.status그리고.Response.statusText결과 응답 개체를 채울 수 있습니다.

fetch(url)
  .then(handleResponse)
  .then((responseJson) => {
    // Do something with the response
  })
  .catch((error) => {
    console.log(error)
  });

export const handleResponse = (res) => {
  if (!res.ok) {
    return res
      .text()
      .then(result => JSON.parse(result))
      .then(result => Promise.reject({ status: result.status, message: result.message }));
  }
  return res
    .json()
    .then(result => Promise.resolve(result))
    .catch(() => Promise.resolve({ status: res.status, message: res.statusText }));
};

이것이 내가 던지는 데 도움이 되기를 바랍니다 오류가 작동하지 않습니다.

function handleErrors(response) {
  if (!response.ok) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        reject({
          status: response.status,
          statusText: response.statusText,
        });
      }, 0);
    });
  }
  return response.json();
}

function clickHandler(event) {
  const textInput = input.value;
  let output;
  fetch(`${URL}${encodeURI(textInput)}`)
    .then(handleErrors)
    .then((json) => {
      output = json.contents.translated;
      console.log(output);
      outputDiv.innerHTML = "<p>" + output + "</p>";
    })
    .catch((error) => alert(error.statusText));

}

부울당 성공적인 응답(상태 200 - 299)을 나타내는 -ok 속성을 사용하여 응답 개체의 상태를 확인했습니다.

$promise.then( function successCallback(response) {  
  console.log(response);
  if (response.ok) { ... }
});

언급URL : https://stackoverflow.com/questions/38235715/fetch-reject-promise-and-catch-the-error-if-status-is-not-ok

반응형