async/await와promises를 사용하여 오류 처리

(헌터 뉴턴이 언스플래시에서 촬영)
나는 승낙하는 것을 좋아한다.그것들은 비동기적인 행위의 가장 좋은 모델이며, await 지옥으로 돌아가는 것을 피하는 것이 매우 쉽다. (비록 나는 약속 자체가 이 점을 잘 할 수 있다고 생각하지만.)일단 당신이 어떻게 일을 할 것인지를 약속하는 심지 모델을 세울 수 있다면, 몇 줄의 코드에서 매우 복잡한 비동기적인 흐름을 세울 수 있다.
비록 나는 공구상자 속의 async/await를 매우 좋아하지만, 그것을 사용할 때, 처리 오류에 몇 가지 괴벽이 있다.오류 처리 방식을 작성하는 것은 매우 간단합니다. 원하는 것보다 더 많은 오류를 삼킬 수 있기 때문에, 이 문제들을 해결하는 전략은 async/await가 가져오는 읽을 수 있는 장점을 부정합니다.
async/await에서 약속을 기다리는 동안 오류를 처리하는 흔한 방법은try/catch 블록을 사용하여 포장하는 것입니다.이것은 상대적으로 간단한 실패 사례를 초래했다. try 블록에서 다른 작업을 수행하면 버려진 모든 이상이 포착될 것이다.

일반 비동기식/대기
async () => {
  try {
    const data = await fetchData();
    doSomethingComplex(data);
  } catch (e) {
    // Any errors thrown by `fetchData` or `doSomethingComplex` are caught.
  }
}
이것은 async/await와 JS 이상 사이의 불행한 상호작용이다.만약 JS에 특정한 이상만 포획하는 메커니즘이 있다면, 우리는 우리가 처리하고자 하는 오류를 더욱 정확하게 묘사할 수 있을 것이다.물론, 우리는 자바를 작성해야 한다.
가장 뚜렷한 해결 방안은 무거운 물건을 try 블록으로 옮기는 것이지만, 이것은 만족스럽지 않다.데이터 흐름이 이상해져서 하나의 값만 있어도 사용할 수 없음const.
try 블록에서 추출한 논리
async () => {
  let data;
  try {
    data = await fetchData();
  } catch (e) {
    // Only errors from `fetchData` are caught.
    return;
  }
  doSomethingComplex(data);
};
이 코드는 읽기에 그다지 유쾌하지 않고, 더 많은 잠재적인 가장자리 상황을 처리할 때 더욱 불쾌하게 변할 뿐이다.그것은 규율을 지켜야 하고, 미래에 의외로 잘못을 삼킬 수도 있다.규율을 정확하게 유지해야 하는 코드는 문제가 있다.일정한 범위 내에서 인위적인 잘못은 피할 수 없다.
그러나 약속을 기다리는 것은 사라지지 않는다.여전히 약속이 있기 때문에, 너는 기다리지 않고 잘못을 처리할 수 있다.

대기 시간.catch()
async () => {
  const data = await fetchData().catch(e => {
    // Only errors from `fetchData` are caught.
  });
  if (!data) return;
  doSomethingComplex(data);
};

대부분의 경우 오류 처리가 상대적으로 독립적이기 때문에 이것은 매우 효과적이다.성공적인 사례는 잘못된 처리를 통해 이상한 코드 구조를 강제로 적용할 필요는 없지만 데이터에 빈 검사를 추가해야 하기 때문에 Wait의 이점을 누릴 수 있습니다.더 복잡한 비동기류에 대해 나는 이것이 더욱 쉽게 읽고 직관적으로 작성될 것이라고 생각한다.빈 검사는 잊어버리기 쉬우며, 복잡한 흐름을 작성할 때 빠뜨리기 쉬운 오류가 발생할 수 있습니다.
버그를 도입하지 않은 상태에서는 오류를 처리하기 어려우므로 브라우저에서 실행되는 모든 것을 피하는 것을 좋아합니다async/await.내가 실패 사례에 관심이 없을 때, 이것은 아주 좋은 편리함이지만, 프로그래밍은 어려운 것이고, 오류가 삼켜질 때 프로그래밍은 더욱 어렵다.너무 많은 함정await이 널리 사용되지 않는다.

약속은요?
async/await 약속이 없는 경우 오류 처리 선택이 더 간단합니다.두 가지 옵션만 있습니다: .catch() 또는 .then()의 두 번째 매개 변수입니다.그들은 내가 한 a demo for a few weeks ago의 주요 차이점을 가지고 있다.

약속.catch()
() => {
  fetchData()
    .then(data => {
      doSomethingComplex(data);
    })
    .catch(err => {
      // Errors from `fetchData` and `doSomethingComplex` end up here.
    });
};
이것은 우리의 첫 번째try/catch 블록과 같은 문제입니다. 과도한 처리 오류입니다.결국, 편집doSomethingComplex에서 오류를 입력할 때, 나는 오류를 볼 수 없기 때문에 시간을 낭비할 것이다.반대로, 나는 error 파라미터를 사용하여 표시하는 것을 더욱 좋아한다. .then()
  fetchData()
    .then(
      data => {
        doSomethingComplex(data);
      },
      err => {
        // Only errors from `fetchData` are caught.
      }
    );
};
나는 아주 적게 사용한다.catch().나는 성공 사례 중의 오류가 내가 볼 수 있는 곳으로 전파되기를 바란다.그렇지 않으면 개발 과정에서 어떤 문제도 무시되고 내가 의식하지 못한 상황에서 버그를 발표할 가능성이 높아진다.
하지만 나는 잘못을 정확하게 처리하는 것을 더 좋아한다.나는 버그가 수면 위로 떠오르는 것을 더 좋아한다. 이렇게 하면 그것들이 관찰되고 복구될 수 있다.만약 사용자 인터페이스에서 발생하는 모든 문제를 계속 처리하고 싶다면, 오류의 전파를 막는 것이 바람직할 수도 있다.이렇게 하면 심각한 고장만 기록할 수 있다는 것을 주의하세요.

기타 질문
내가 약속에서 직면한 중요한 문제는 약속의 실수가 항상 거절을 초래할 수 있다는 것이다.만약 외부 데이터의 추상적인 것을 개발하고 있다면, 이것은 문제가 될 수 있습니다.처리 거부 프로그램이 네트워크 오류만 처리하겠다고 약속하면 오류가 발생합니다.비네트워크 이상은 버그 추적 도구에 나타나지 않거나 중요한 상하문을 잃어버릴 수 있습니다.
const fetchData = () =>
  requestData().then(({ data }) =>
    // What if `removeUnusedFields` throws?
    // It could reference a field on `undefined`, for example.
    data.map(removeUnusedFields)
  );

//
fetchData().then(handleSuccess, err => {
  // This code path is called!
});
이것이 바로 약속의 표현이지만 개발 과정에서 나는 여러 번 고통스러웠다.간단한 해결 방안이 하나도 없기 때문에 개발 과정에서 이 점을 기억해야 한다.이것은 생산 과정에서 자발적으로 발생할 수 없지만 코드를 편집할 때 시간이 걸릴 수 있다.
코드를 작성할 때, 항상 알 수 없는 요소가 있기 때문에, 오류 처리가 최종적으로 그것을 처리하지 않는 것으로 실행될 것이라고 안전하게 가정할 수 있다.부정확한 오류 처리는 생산력과 오류 수량에 막대한 비용을 초래할 수 있다.최근에 일련의 복잡한 비동기 작업을 편집할 때, 이 작업들은try/catch로 기다리는 예를 만났다.이것은try에서 마지막 함수 호출을 던졌습니다. 실행 성공과 실패 코드 경로입니다.나는 이런 행동에 주의하는 데 시간이 좀 걸렸고, 왜 이런 일이 일어났는지 이해하는 데 더 오랜 시간이 걸렸다.
전반적으로 말하면, 많은 방법들이 너로 하여금 잘못을 처리할 때 불리한 위치에 처하게 할 수 있다.오류가 어떻게 전파될지 이해하면 오류를 용인하는 코드를 작성하는 데 도움이 될 것이다.오류를 정확하게 처리하고 피하는 것overly defensive code 사이에는 좋은 경계선이 있지만 장기적으로 보면 이익을 가져올 것이다.
미래를 내다보면 pattern matching(본문을 작성할 때stage 1)를 늘리는 것이 오류를 정확하게 처리하는 데 강력한 도구가 될 것이라는 제안이 나온다.JS 생태계의 다른 부분에 서로 다른 오류 묘사 방식을 사용한 것을 감안하면 패턴 일치는 좋은 오류 묘사 방식인 것 같다.
약속한 더 많은 읽기에 관해서 저는 this post by Nolan Lawson를 추천합니다. 이것은 제가 이 글의 초기 초고에 대한 회답을 받은 것입니다.흥미로운 것은 처리.then()의 오류를 피하고 지원.catch()을 하며 다양한 각도에서 읽는 것이 좋다는 것이다.이 책은 약속을 함께 쓰는 것에 관한 것이 더 많은데, 이것은 내가 조금도 언급하지 않은 것이다.
읽어주셔서 감사합니다!내가 트위터에 올린 신분은 (그러나 대부분의 다른 곳은 vcarl) 이다.I moderateReactiflux는 리액트 개발자의 대화방, I moderateNodeiflux는 노드의 대화방이다.JS 개발자.만약 당신에게 어떤 문제나 건의가 있다면, 우리에게 연락하세요.

좋은 웹페이지 즐겨찾기