[javascript] .then (성공, 실패)은 언제 약속의 반 패턴으로 간주됩니까?

나는 한 번 봐했다 블루 버드 약속 자주 묻는 질문 은 그 언급하는, .then(success, fail)안티 패턴입니다 . 시도와 캐치에 대한 설명을 이해하지 못합니다. 다음과 관련하여 무엇이 문제입니까?

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })

예제는 다음을 올바른 방법으로 제안하는 것 같습니다.

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })

차이점이 뭐야?



답변

차이점이 뭐야?

.then()호출은 콜백에서 오류가 발생하는 경우에 거부됩니다 약속을 반환합니다. 즉, 성공에 logger실패하면 오류가 다음 .catch()콜백 으로 전달 fail되지만와 함께 발생 하는 콜백 에는 전달 되지 않습니다 success.

제어 흐름도 는 다음과 같습니다 .

두 개의 인수로 제어 흐름 다이어그램
캐치 체인의 제어 흐름도

동기 코드로 표시하려면 다음을 수행하십시오.

// some_promise_call().then(logger.log, logger.log)
then: {
    try {
        var results = some_call();
    } catch(e) {
        logger.log(e);
        break then;
    } // else
        logger.log(results);
}

두 번째 log(첫 번째 인수와 같음 .then())는 예외가 발생하지 않은 경우에만 실행됩니다. 레이블이 붙은 블록과 break문장은 약간 이상하게 느껴집니다. 실제로 파이썬이 가지고있는 것 try-except-else입니다 (권장 독서!).

// some_promise_call().then(logger.log).catch(logger.log)
try {
    var results = some_call();
    logger.log(results);
} catch(e) {
    logger.log(e);
}

catch로거는 성공 로거 호출에서 예외를 처리합니다.

차이점이 너무 많습니다.

시도와 캐치에 대한 설명을 잘 이해하지 못합니다.

논쟁은 일반적으로 처리의 모든 단계에서 오류를 포착하고 체인에서 사용해서는 안된다는 것입니다. “antipattern”을 사용할 때 일부 콜백의 오류는 처리되지 않지만 모든 오류를 처리하는 최종 처리기는 하나만 있어야합니다.

그러나이 패턴은 실제로 매우 유용합니다. 정확하게이 단계에서 발생한 오류를 처리하고 오류가 발생하지 않은 경우 (예 : 오류를 복구 할 수없는 경우) 완전히 다른 작업을 수행하려는 경우. 이것이 제어 흐름을 분기 한다는 점에 유의 하십시오 . 물론 이것은 때때로 바람직하다.


다음과 관련하여 무엇이 문제입니까?

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })

콜백을 반복해야한다고 당신은 오히려 원합니다

some_promise_call()
   .catch(function(e) {
       return e; // it's OK, we'll just log it
   })
   .done(function(res) {
       logger.log(res);
   });

.finally()이것을 위해 사용 하는 것도 고려할 수 있습니다 .


답변

둘은 동일하지 않습니다. 차이점은 첫 번째 예제는 success핸들러 에서 발생한 예외를 포착하지 않는다는 것 입니다. 따라서 메소드가 해결 된 약속 만 반환 해야하는 경우가 종종 있지만 후행 catch핸들러 (또는 thensuccess매개 변수 가있는 다른 핸들러) 가 필요합니다 . 물론 then핸들러가 잠재적으로 실패 할 수있는 작업을 수행하지 않을 then수 있습니다. 이 경우 하나의 2 매개 변수 를 사용하는 것이 좋습니다.

그러나 당신이 연결된 텍스트의 요점은 then많은 비동기 단계를 연결하는 기능에서 콜백과 비교하여 대부분 유용하다는 것입니다. 실제로이 작업을 수행 할 때 2 매개 변수 형식의 then미묘하게 예상대로 작동하지 않습니다 위의 이유로. 미드 체인을 사용할 때 특히 직관적입니다.

많은 복잡한 비동기 작업을 수행하고 인정해야 할 것보다 이와 같은 구석에 부딪친 사람은이 안티 패턴을 피하고 별도의 처리기 접근 방식을 따르는 것이 좋습니다.


답변

두 가지의 장단점을 살펴보면 상황에 적합한 계산 된 추측을 할 수 있습니다. 이것이 약속 이행에 대한 두 가지 주요 접근법입니다. 둘 다 플러스와 마이너스

캐치 접근법

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })

장점

  1. 모든 오류는 하나의 catch 블록으로 처리됩니다.
  2. then 블록에서 예외를 잡습니다.
  3. 여러 성공 콜백 체인

단점

  1. 연결하는 경우 다른 오류 메시지를 표시하기가 어렵습니다.

성공 / 오류 접근

some_promise_call()
.then(function success(res) { logger.log(res) },
      function error(err) { logger.log(err) })

장점

  1. 세밀한 오류 제어가 가능합니다.
  2. db error, 500 error 등과 같은 다양한 범주의 오류에 대해 일반적인 오류 처리 기능을 사용할 수 있습니다.

Disavantages

  1. catch성공 콜백에 의해 발생한 오류를 처리하려면 여전히 다른 것이 필요합니다.

답변

간단한 설명 :

ES2018에서

catch 메소드가 onRejected 인수와 함께 호출되면 다음 단계가 수행됩니다.

  1. 약속이이 가치가되게하십시오.
  2. 돌아온다? 호출 (약속, “then”,«정의되지 않음, onRejected»).

그것의 의미는:

promise.then(f1).catch(f2)

같다

promise.then(f1).then(undefiend, f2)


답변

사용을 .then().catch()사용하면 워크 플로를 수행하는 데 필요한 Promise Chaining 을 활성화 할 수 있습니다 . 데이터베이스에서 일부 정보를 읽은 다음 비동기 API로 전달한 다음 응답을 조작하려고 할 수 있습니다. 응답을 데이터베이스로 다시 푸시 할 수 있습니다. 개념으로 이러한 모든 워크 플로를 처리하는 것은 가능하지만 관리하기가 매우 어렵습니다. 더 나은 해결책은 then().then().then().then().catch()모든 오류를 한 번에 잡아서 코드 의 유지 관리 성 을 유지할 수있게하는 것 입니다.


답변

약속에 체인 성공 및 실패 처리기를 사용 then()하고 catch()도와줍니다. catch()에서 반환 한 약속에 따라 작동합니다 then(). 처리합니다.

  1. 약속이 거절 된 경우. 그림에서 # 3 참조
  2. then ()의 성공 핸들러에서 오류가 발생하면 아래 행 번호 4-7 사이입니다. 그림의 # 2.a를 참조하십시오 (실패 콜백은 then()이를 처리하지 않습니다).
  3. then ()의 실패 처리기에서 오류가 발생한 경우, 행 번호 8은 아래에 있습니다. 그림의 # 3.b를 참조하십시오.


1. let promiseRef: Promise = this. aTimetakingTask (false);
2. promiseRef
3. .then(
4. (result) => {
5. /* successfully, resolved promise.
6. Work on data here */
7. },
8. (error) => console.log(error)
9. )
10. .catch( (e) => {
11. /* successfully, resolved promise.
12. Work on data here */
13. });

여기에 이미지 설명을 입력하십시오

참고 : 많은 경우 실패 핸들러가 catch()이미 작성된 경우 실패 핸들러가 정의되지 않을 수 있습니다 . 편집 : 오류 처리기 가 정의 되지 않은 경우에만 reject()호출 catch()됩니다 . 그림의 # 3을로 확인하십시오 . 라인 # 8 및 9의 핸들러가 정의되지 않은 경우 호출됩니다.then()catch()

then()콜백이 돌보는 경우에 의해 반환 된 약속 에는 오류가 없으므로 의미 가 있습니다.


답변

좋은 예입니다. 다음 코드 (첫 번째 약속이 해결 된 경우) :

Promise.resolve()
.then
(
  () => { throw new Error('Error occurs'); },
  err => console.log('This error is caught:', err)
);

다음과 동일합니다 :

Promise.resolve()
.catch
(
  err => console.log('This error is caught:', err)
)
.then
(
  () => { throw new Error('Error occurs'); }
)

그러나 첫 번째 약속이 거부되었으므로 이것은 동일하지 않습니다.

Promise.reject()
.then
(
  () => { throw new Error('Error occurs'); },
  err => console.log('This error is caught:', err)
);

Promise.reject()
.catch
(
  err => console.log('This error is caught:', err)
)
.then
(
  () => { throw new Error('Error occurs'); }
)