[javascript] 명시 적 약속 건설 반 패턴은 무엇이며 어떻게 방지합니까?

나는 다음과 같은 것을하는 코드를 작성하고있었습니다.

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예외가 발생한 경우). 그것은 처리되지 않고 새 약속을 해결하지 않은 채로 둡니다.

반대로, using .then()은 이러한 두 시나리오를 자동으로 처리하고 오류가 발생하면 새로운 약속을 거부합니다.

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

지연된 반 패턴은 번거로울뿐만 아니라 오류가 발생하기 쉽습니다 . .then()체인에 사용 하는 것이 훨씬 안전합니다.

그러나 나는 모든 것을 처리했습니다!

정말? 좋은. 그러나 특히 취소 또는 메시지 전달과 같은 다른 기능을 지원하는 약속 라이브러리를 사용하는 경우 매우 상세하고 풍부합니다. 아니면 미래에 또는 라이브러리를 더 나은 라이브러리로 바꾸고 싶습니까? 이를 위해 코드를 다시 작성하고 싶지 않을 것입니다.

라이브러리의 메소드 ( then)는 모든 기능을 기본적으로 지원할뿐만 아니라 특정 최적화 기능을 갖추고있을 수도 있습니다. 그것들을 사용하면 코드가 더 빨라지거나 최소한 라이브러리의 개정판으로 최적화 될 수 있습니다.

어떻게 피할 수 있습니까?

따라서 수동으로 작성 Promise하거나 Deferred이미 존재하는 약속이 포함되어 있으면 라이브러리 API를 먼저 확인하십시오 . 하지만 – 이연 안티 패턴은 종종 [전용] 관찰자 패턴으로 약속을 볼 사람들에 의해 적용되는 약속이 콜백 이상을 : 그들이 해야하는 작성 가능합니다. 모든 양질의 라이브러리에는 다루기 싫은 모든 하위 수준의 자료를 처리하면서 모든 생각할 수있는 방식으로 약속을 구성하는 데 사용하기 쉬운 많은 기능이 있습니다.

기존 헬퍼 함수에서 지원하지 않는 새로운 방식으로 일부 약속을 작성해야하는 경우, 피할 수없는 지연으로 고유 한 함수를 작성하는 것이 마지막 옵션이어야합니다. 보다 유용한 라이브러리로 전환하거나 현재 라이브러리에 버그를 신고하십시오. 관리자는 기존 기능에서 컴포지션을 도출하고, 새로운 도우미 기능을 구현하고 /하거나 처리해야하는 에지 사례를 식별 할 수 있어야합니다.


답변