[jquery] jQuery deferred의 “then”메서드는 언제 사용해야하며 “pipe”메서드는 언제 사용해야합니까?

jQuery Deferred에는 함수의 비동기 체인을 구현하는 데 사용할 수있는 두 가지 함수가 있습니다.

then()

deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred

doneCallbacks Deferred가 해결 될 때 호출되는 함수 또는 함수 배열입니다.
failCallbacks Deferred가 거부 될 때 호출되는 함수 또는 함수 배열입니다.

pipe()

deferred.pipe( [doneFilter] [, failFilter] ) Returns: Promise

doneFilter Deferred가 해결 될 때 호출되는 선택적 함수입니다.
failFilter Deferred가 거부 될 때 호출되는 선택적 함수입니다.

나는 then()그보다 조금 더 오래되었다는 것을 알고 pipe()있으므로 후자는 약간의 추가 이점을 추가해야하지만 그 차이가 정확히 무엇인지 알 수 없습니다. 둘 다 이름이 다르지만 거의 동일한 콜백 매개 변수를 사용하며 a를 반환하는 Deferred것과 a 를 반환하는 것의 차이 Promise는 약간 보입니다.

저는 공식 문서를 계속해서 읽었지만 항상 너무 “밀집되어”머리를 감쌀 수 없으며 검색을 통해 한 기능 또는 다른 기능에 대해 많은 토론을 찾았지만 실제로 다른 기능을 명확히하는 것을 찾지 못했습니다. 각각의 장단점.

그렇다면 언제 사용하는 then것이 더 좋으며 언제 사용하는 것이 더 좋 pipe습니까?


덧셈

Felix의 탁월한 답변 은이 두 기능이 어떻게 다른지 명확히하는 데 도움이되었습니다. 그러나 나는의 기능이 때 시간이 있는지 궁금 then()의 그것 바람직하다 pipe().

전자가 후자가 할 수있는 모든 것을 할 수있는 것 pipe()보다 더 강력한 것이 분명합니다 then(). 사용하는 한 가지 이유 then()는 이름이 동일한 데이터를 처리하는 기능 체인의 종료로서의 역할을 반영 하기 때문일 수 있습니다.

그러나 새로운 반환으로 인해 할 수없는 then()원본 Deferred을 반환 해야하는 사용 사례가 있습니까?pipe()Promise



답변

이후 jQuery를 1.8 .then 로 동일하게 동작합니다 .pipe:

지원 중단 알림 : jQuery 1.8부터이 deferred.pipe()메서드는 더 이상 사용되지 않습니다. deferred.then()를 대체하는 방법은 대신 사용해야합니다.

jQuery를 1.8으로deferred.then()방법은 지금은 사용되지 않는 대신, 상태 및 기능을 통해 지연된의 값을 필터링 할 수있는 새로운 약속을 반환하는 deferred.pipe()방법을.

아래의 예는 여전히 도움이 될 수 있습니다.


그들은 다른 목적으로 사용됩니다.

  • .then()프로세스의 결과로 작업하고 싶을 때, 즉 문서에서 말하는 것처럼 지연된 객체가 해결되거나 거부 될 때 사용됩니다. 그것은 사용하는 것과 동일 .done()하거나 .fail().

  • 어떻게 든 결과 .pipe()를 (사전) 필터링 하는 데 사용 합니다 . 콜백의 반환 값은 및 콜백에 .pipe()인수로 전달됩니다 . 또한 다른 지연된 객체를 반환 할 수 있으며 다음 콜백이이 지연된 항목에 등록됩니다.donefail

    .then()(또는 .done(), .fail()) 의 경우 가 아니라 등록 된 콜백의 반환 값이 무시됩니다.

그래서 사용하는 것이 아닌 하나 .then() 또는 .pipe() . 당신은 할 수 사용 .pipe()과 같은 목적으로 .then()하지만, 그 반대는 유지되지 않습니다.


예 1

일부 작업의 결과는 객체의 배열입니다.

[{value: 2}, {value: 4}, {value: 6}]

값의 최소값과 최대 값을 계산하려고합니다. 두 개의 done콜백 을 사용한다고 가정 해 보겠습니다 .

deferred.then(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    var min = Math.min.apply(Math, values);

   /* do something with "min" */

}).then(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    var max = Math.max.apply(Math, values);

   /* do something with "max" */

});

두 경우 모두 목록을 반복하고 각 개체에서 값을 추출해야합니다.

두 콜백에서 개별적으로이 작업을 수행 할 필요가 없도록 미리 값을 추출하는 것이 더 낫지 않을까요? 예! 그리고 그것이 우리가 사용할 수있는 것 .pipe()입니다 :

deferred.pipe(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    return values; // [2, 4, 6]

}).then(function(result) {
    // result = [2, 4, 6]

    var min = Math.min.apply(Math, result);

    /* do something with "min" */

}).then(function(result) {
    // result = [2, 4, 6]

    var max = Math.max.apply(Math, result);

    /* do something with "max" */

});

분명히 이것은 구성된 예이며이 문제를 해결하기위한 여러 가지 (아마도 더 나은) 방법이 있지만 요점을 설명하기를 바랍니다.


예 2

Ajax 호출을 고려하십시오. 때로는 이전 호출이 완료된 후 하나의 Ajax 호출을 시작하려고합니다. 한 가지 방법은 done콜백 내에서 두 번째 호출을 만드는 것입니다 .

$.ajax(...).done(function() {
    // executed after first Ajax
    $.ajax(...).done(function() {
        // executed after second call
    });
});

이제 코드를 분리하고 다음 두 Ajax 호출을 함수 안에 넣길 원한다고 가정합니다.

function makeCalls() {
    // here we return the return value of `$.ajax().done()`, which
    // is the same deferred object as returned by `$.ajax()` alone

    return $.ajax(...).done(function() {
        // executed after first call
        $.ajax(...).done(function() {
            // executed after second call
        });
    });
}

두 번째 Ajax 호출에 makeCalls대한 콜백을 첨부하기 위해 호출 하는 다른 코드를 허용하기 위해 지연된 객체를 사용하고 싶지만

makeCalls().done(function() {
    // this is executed after the first Ajax call
});

두 번째 호출이 done콜백 내부에서 이루어 지고 외부에서 액세스 할 수 없기 때문에 원하는 효과를 얻지 못할 것 입니다.

해결책은 .pipe()대신 사용하는 것입니다.

function makeCalls() {
    // here we return the return value of `$.ajax().pipe()`, which is
    // a new deferred/promise object and connected to the one returned
    // by the callback passed to `pipe`

    return $.ajax(...).pipe(function() {
        // executed after first call
        return $.ajax(...).done(function() {
            // executed after second call
        });
    });
}

makeCalls().done(function() {
    // this is executed after the second Ajax call
});

를 사용 .pipe()하면 호출의 실제 흐름 / 순서를 노출하지 않고도 “내부”Ajax 호출에 콜백을 추가 할 수 있습니다.


일반적으로 지연된 객체는 코드를 분리하는 흥미로운 방법을 제공합니다. 🙂


답변

을 반드시 사용해야 then()하는 경우는 없습니다 pipe(). pipe()전달 될 값을 항상 무시하도록 선택할 수 있습니다 . 사용시 약간의 성능 저하 가 있을pipe있지만 문제가되지는 않습니다.

따라서 pipe()두 경우 모두 단순히 항상 사용할 수있는 것처럼 보일 수 있습니다 . 그러나을 사용 pipe()하면 코드를 읽는 다른 사람 (지금부터 6 개월 후 자신을 포함)에게 반환 값이 중요하다는 사실 을 알릴 수 있습니다. 폐기하는 경우이 의미 구조를 위반하는 것입니다.

사용되지 않는 값을 반환하는 함수가있는 것과 같습니다. 혼란 스럽습니다.

그러니 then()필요할 때와해야 할 때 사용하십시오 pipe().


답변

실제로 .then()와 사이의 차이는 .pipe()불필요한 것으로 간주되었으며 jQuery 버전 1.8과 동일하게 만들어졌습니다.

에서 에 의해 코멘트jaubourg jQuery의 버그 트래커에 티켓 # 11010 “MAKE DEFERRED.THEN == DEFERRED.PIPE LIKE 약속 / A”

1.8에서는 이전 버전을 제거하고 현재 파이프로 교체합니다. 그러나 매우 슬픈 결과는 사람들에게 비표준 done, fail 및 progress를 사용하도록 알려야한다는 것입니다. 제안이 단순하고 효율적이며 콜백을 추가한다는 의미를 제공하지 않기 때문입니다.

(엠파 시스 광산)


답변