jQuery deferred의 "then"메서드는 언제 사용해야하며 "pipe"메서드는 언제 사용해야합니까?


97

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


1
나는 이것에 대해 잠시 생각했지만 tbh, 나는 어떤 사용 사례도 생각할 수 없습니다. 필요하지 않은 경우 새 promise 객체를 생성하는 것은 오버 헤드 일 수 있습니다 (내부적으로 어떻게 연결되어 있는지 모르겠습니다). 즉, 저보다 이것을 더 잘 이해하는 사람들이 분명히 있습니다.
Felix Kling

6
이 질문에 관심이있는 사람은 반드시 jQuery를 버그 트래커에 티켓 # 11010에 관심이있을 것입니다 : MAKE DEFERRED.THEN == DEFERRED.PIPE LIKE 약속 / A
hippietrail

답변:


103

이후 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 호출에 콜백을 추가 할 수 있습니다.


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


아 예 할 수없는 pipe필터링을 then할 수 있다는 것을 간과했습니다 . 그러나 인터넷 검색에서 이러한 주제 는 필터링이 그와 함께 제공되는 보너스 추가 항목으로 간주 되었기 때문에 pipe대신 호출을 선택한 것으로 보이지만 실제 목적을 더 명확하게 표시했습니다. 따라서 필터링 외에 다른 차이점이있을 것 같습니다. (그럼 다시 내가 정말 심지어 예와 필터링 기능을 이해하지 못하는 인정해야. 수 그런데?)filterpiperesult values;return values;
hippietrail

내가 당신의 예를 이해하지 못한다고 말할 때, 다음과 같은 것 .then()입니까? 위의 예 에서 result두는 매번 필터링 하는 동일한 데이터를 수신합니다 . 아래 예제에서는 두 개의 후속 s가 수신 할 때 전달하기 전에 .pipe()데이터의 일부를 제거 합니까? resultresult.then()
hippietrail 2012 년

1
@hippietrail : 그 동안 내 답변을 업데이트하고 .pipe(). 콜백이 지연된 객체를 반환하면 후속 완료 또는 실패 콜백이 해당 객체에 등록됩니다. 다른 예를 포함하겠습니다. 편집 : 두 번째 의견에 대해 : 예.
Felix Kling 2012 년

따라서 한 가지 차이점은 데이터가 통과 pipe() 하는 반면 끝에서 데이터를 사용해야하고 then()더 이상 흐르지 않는 리프 노드 와 비슷하며 a 를 then()반환 한다는 사실에도 불구하고 Deferred실제로 사용 / 유용하지 않다는 것입니다. 이것이 옳다면 /* do something with "min"/"max" */각 ".then () 절" 과 같은 것을 포함하도록 명확히하는 것이 도움이 될 수 있습니다 .
hippietrail

1
걱정하지 마세요. :) 지연된 객체와 그 메서드가 어떻게 작동하는지 완전히 이해하는데도 시간이 걸렸습니다. 그러나 일단 이해하면 더 이상 어렵지 않은 것 같습니다. 나는 문서가 아마도 더 쉬운 방법으로 작성 될 수 있다는 데 동의합니다.
Felix Kling 2012 년

7

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

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

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

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


3
K. Scott Allen의 블로그 "Experiments In Writing"에서 두 가지를 사용한 실제 예제를 찾았습니다. Geolocation, Geocoding 및 jQuery Promises : "그러면 제어 논리가 꽤 잘 읽 힙니다." $(function () { $.when(getPosition()) .pipe(lookupCountry) .then(displayResults); }); "파이프가 파이프가 새로운 약속을 돌려주기 때문입니다. "
hippietrail

5

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

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

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

(엠파 시스 광산)


1
지금까지 최고의 참조, 고급 사용법을 찾고 있습니다.
TWiStErRob
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.