IT

명시적 약속 구성 반대는 무엇이며 어떻게 피해야 합니까?

itgroup 2022. 11. 7. 21:27
반응형

명시적 약속 구성 반대는 무엇이며 어떻게 피해야 합니까?

나는 다음과 같은 동작을 하는 코드를 쓰고 있었다.

function getStuffDone(param) {           | function getStuffDone(param) {
    var d = Q.defer(); /* or $q.defer */ |     return new Promise(function(resolve, reject) {
    // or = new $.Deferred() etc.        |     // using a promise constructor
    myPromiseFn(param+1)                 |         myPromiseFn(param+1)
    .then(function(val) { /* or .done */ |         .then(function(val) {
        d.resolve(val);                  |             resolve(val);
    }).catch(function(err) { /* .fail */ |         }).catch(function(err) {
        d.reject(err);                   |             reject(err);
    });                                  |         });
    return d.promise; /* or promise() */ |     });
}                                        | }

어떤 분이 이걸 각각 '지연된 대항마' 또는 '컨스트럭터 대항마'Promise라고 하는데, 이 코드의 어떤 점이 나쁜지, 왜 이걸 '대향마'라고 부르나요?

Esailija가 만든 이연 안티패턴(현재의 명시적 건설 안티패턴)은 약속을 처음 하는 사람들이 흔히 하는 안티패턴으로, 제가 처음 공약을 사용했을 때 직접 만든 것입니다.위의 코드의 문제는 가 약속 체인을 이용하지 못한다는 것입니다.

약속과 결부될 수 있다.then이치★★★★★★★★★★★★★★★★★★★★★의 코드:getStuffDone이치하다

function getStuffDone(param){
    return myPromiseFn(param+1); // much nicer, right?
}

약속은 비동기 코드를 보다 쉽게 읽을 수 있도록 하는 것이며, 이러한 사실을 숨기지 않고 동기 코드처럼 작동합니다.약속은 일회성 연산 값에 대한 추상화를 나타내며, 프로그래밍 언어에서 문장 또는 표현식의 개념을 추상화합니다.

API를 약속으로 변환하여 자동으로 실행할 수 없거나 이렇게 표현하기 쉬운 집계 함수를 작성할 때만 지연 개체를 사용해야 합니다.

Esailija 인용:

이것은 가장 일반적인 안티 패턴입니다.약속을 제대로 이해하지 못하고 미화된 이벤트 발신자 또는 콜백 유틸리티로 생각할 때 이 문제에 빠지기 쉽습니다.요약하자면, 약속은 플랫 들여쓰기나 하나의 예외 채널과 같은 동기 코드의 손실된 속성 대부분을 비동기 코드로 유지하도록 하는 것입니다.

무슨 문제라도 있습니까?

하지만 패턴은 효과가 있어!

운이 좋으시네요.유감스럽게도 그렇지 않을 수 있습니다.가장자리에 있는 케이스를 잊어버렸을 가능성이 높기 때문입니다.지금까지의 절반 이상의 경우, 작성자는 에러 핸들러를 처리하는 것을 잊었습니다.

return new Promise(function(resolve) {
    getOtherPromise().then(function(result) {
        resolve(result.property.example);
    });
})

만약 다른 약속이 거부된다면, 이것은 (어디서 처리될지) 새로운 약속으로 전파되지 않고 눈에 띄지 않게 일어날 것이고, 새로운 약속은 영원히 보류되어 유출을 야기할 수 있다.

이 발생합니다. 콜백 코드가 에러를 일으킨 경우입니다.result이 없다property예외는 무시됩니다.그것은 처리되지 않고 새로운 약속이 해결되지 않은 채로 남겨질 것이다.

'는 사용법'을 사용합니다..then()는, 양쪽의해, 발생했을 합니다.이러한 경우는, 새로운 약속을 거부합니다.

 return getOtherPromise().then(function(result) {
     return result.property.example;
 })

지연된 반격은 번거로울 뿐만 아니라 오류가 발생하기 쉽습니다.사용..then()체인이 훨씬 안전하기 때문입니다.

하지만 내가 다 처리했어!

그래요? 좋아요.그러나 취소나 메시지 전달과 같은 다른 기능을 지원하는 약속 라이브러리를 사용하는 경우, 이 작업은 매우 상세하고 복잡합니다.아니면 나중에 그럴 수도 있고 아니면 라이브러리를 더 나은 라이브러리와 바꾸고 싶으신가요?당신은 그것을 위해 코드를 다시 쓰는 것을 원하지 않을 것이다.

도서관의 방법)then는 모든로 지원할 만 아니라 기능을 있을 수도 는 모든 기능을 네이티브로 지원할 뿐만 아니라 특정 최적화 기능을 갖추고 있을 수도 있습니다.이러한 기능을 사용하면 코드가 빨라지거나 라이브러리의 향후 리비전을 통해 최적화될 수 있습니다.

어떻게 피하지?

당신이 것을 Promise ★★★★★★★★★★★★★★★★★」Deferred기존 약속이 이미 포함되어 있는 경우 먼저 라이브러리 API를 확인하십시오.지연된 반격은 약속을 관찰자 패턴으로만 보는 사람들에 의해 종종 적용됩니다. 그러나 약속은 콜백 이상입니다. 즉, 그것들은 구성 가능해야 합니다.모든 괜찮은 도서관에는 모든 생각할 수 있는 방식으로 약속을 구성하기 위한 사용하기 쉬운 기능이 많이 있으며, 여러분이 다루기 싫은 모든 낮은 수준의 것들을 처리합니다.

기존 도우미 함수가 지원하지 않는 새로운 방법으로 약속을 작성해야 할 경우 피할 수 없는 지연을 사용하여 자신의 함수를 작성하는 것이 마지막 옵션입니다.보다 기능적인 라이브러리로 전환하거나 현재 라이브러리에 버그를 제기하는 것을 고려해 주십시오.유지관리자는 기존 기능에서 구성을 도출하고 새로운 도우미 기능을 구현하거나 처리해야 할 엣지 케이스를 식별하는 데 도움을 줄 수 있어야 합니다.

7년이 지난 지금, 이 질문에 대한 답은 간단합니다.

명시적 컨스트럭터 안티퍼턴을 피하려면 어떻게 해야 합니까?

사용하다async function그럼await모든 약속!

다음과 같이 중첩된 Promise 체인을 수동으로 구성하는 대신 다음을 수행합니다.

function promised() {
  return new Promise(function(resolve) {
    getOtherPromise().then(function(result) {
      getAnotherPromise(result).then(function(result2) {
        resolve(result2);
      });
    });
  });
}

기능을 전환하기만 하면 됩니다.async를 사용합니다.awaitPromise가 해결될 때까지 함수 실행을 중지하려면 키워드를 지정합니다.

async function promised() {
   const result =  await getOtherPromise();
   const result2 = await getAnotherPromise(result);
   return result2;
}

여기에는 다양한 이점이 있습니다.

  • 를 호출하다async함수는 항상 Promise를 반환합니다.이 값은 반환된 값으로 해결되며 비동기 함수 내에 오류가 발생하면 거부됩니다.
  • 이 경우,awaited Promise rejects, 오류는 비동기 함수에 삽입되므로try { ... } catch(error) { ... }동기 오류처럼요
  • 넌 할 수 있다.await내부 루프 및 분기된 경우 Promise 체인 로직의 대부분을 사소한 것으로 만듭니다.
  • 비동기 함수는 대부분 Promise의 체인처럼 동작하지만 읽기(추리하기)가 훨씬 쉽다.

제가 어떻게.await콜백?

콜백이 한 번만 콜백하고 호출하는 API가 Promise를 이미 제공하지 않는 경우(대부분 제공됨)는 Promise 컨스트럭터를 사용해야 하는 유일한 이유입니다.

 // Create a wrapper around the "old" function taking a callback, passing the 'resolve' function as callback
 const delay = time => new Promise((resolve, reject) =>
   setTimeout(resolve, time)
 ); 

 await delay(1000);

한다면await가 실행을 정지하고 콜을 발신합니까?async function결과를 직접 반환하시겠습니까?

아니요. 비동기 함수를 호출하면 Promise가 항상 반환됩니다.그럼 할 수 있어요await비동기 함수의 내부에서도 약속합니다.동기 함수의 내부에서는 결과를 기다릴 수 없습니다(콜이 필요)..then콜백을 첨부합니다).

입니다.function는 항상 , 는 1개의 작업으로 완료됩니다.async function는 s가 될 됩니다.await그 후, 그들은 다른 일을 계속합니다.

언급URL : https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it

반응형