JavaScript에서 Deferred, Promise 및 Future의 차이점은 무엇입니까?


300

연기, 약속 및 미래의 차이점은 무엇입니까?
이 세 가지 모두에 대해 일반적으로 승인 된 이론이 있습니까?


11
나는 이것이 jQuery와 관련이 있다고 생각하지 않습니다 ...
BoltClock

11
이것을 읽을 가치가있는 : msdn.microsoft.com/en-us/scriptjunkie/gg723713
jfriend00

8
나는 그것들을 직접 사용하지는 않았지만 여기에 wikipedia en.wikipedia.org/wiki/Futures_and_promises 에 대한 좋은 소개가 있습니다. 유스 케이스를 제대로 이해하지 못했지만. 자바 스크립트와 같은 비동기 이벤트 중심 언어. 언뜻보기에 더 깨끗한 API를 제외하고 콜백을 통해 제공하는 것을 볼 수 없습니다. 누군가가 사용 사례를 제공하고 이러한 개념이 적용되는 방법과 콜백이 왜 비효율적 인 솔루션인지 보여줄 수 있다면 좋을 것입니다. @ duri 이것은 jQuery와 관련이 없습니다. jQuery 태그를 제거 할 수 있습니까
AshHeskes

2
@ jfriend00 위대한 링크, 아마 대답으로 작동해야합니다.
fncomp

@ jfriend00 새로운 링크 - msdn.microsoft.com/en-us/magazine/gg723713.aspx
C69

답변:


97

OP의 질문에 대답하려고 시도한 방법에 대한 혐오감을 분명히 나타냅니다. 문자 그대로의 대답은 약속은 다른 객체와 공유되는 것이며 지연된 것은 비공개로 유지해야한다는 것입니다. 기본적으로 지연된 (일반적으로 약속을 연장하는) 지연 자체가 해결 될 수 있지만 약속은 그렇지 않을 수 있습니다.

축소에 관심이 있다면 Promises / A + 를 조사하십시오 .


내가 아는 한, 가장 중요한 목적은 표준화 된 인터페이스를 통해 선명도를 높이고 결합을 느슨하게하는 것입니다. @ jfriend00의 추천 글 을 참조하십시오 :

약속을 사용하여 밀접하게 연결된 인터페이스로 이어질 수있는 콜백을 함수에 직접 전달하는 대신 약속을 사용하면 동기식 또는 비동기 코드에 대한 우려를 분리 할 수 ​​있습니다.

개인적으로 비동기 요청에 의해 채워지는 템플릿, 종속성 네트워크가있는 스크립트로드 및 비 차단 방식으로 데이터를 형성하기 위해 사용자 피드백을 제공하는 등의 작업을 처리 할 때 특히 유용한 지연이 발견되었습니다.

실제로 JS 모드에서 CodeMirror를 비동기 적으로로드 한 후 무언가를 수행하는 순수한 콜백 형식을 비교하십시오 (죄송합니다. 한동안 jQuery를 사용하지 않았습니다 ).

/* assume getScript has signature like: function (path, callback, context) 
   and listens to onload && onreadystatechange */
$(function () {
   getScript('path/to/CodeMirror', getJSMode);

   // onreadystate is not reliable for callback args.
   function getJSMode() {
       getScript('path/to/CodeMirror/mode/javascript/javascript.js', 
           ourAwesomeScript);
   };

   function ourAwesomeScript() {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   };
});

약속 된 버전 (다시 말해서, jQuery에 대해서는 최신 상태가 아닙니다) :

/* Assume getScript returns a promise object */
$(function () {
   $.when(
       getScript('path/to/CodeMirror'),
       getScript('path/to/CodeMirror/mode/javascript/javascript.js')
   ).then(function () {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   });
});

세미 의사 코드에 대한 사과이지만 핵심 아이디어가 다소 명확 해지기를 바랍니다. 기본적으로 표준화 된 약속을 반환하면 약속을 전달할 수 있으므로보다 명확한 그룹화가 가능합니다.


10
이 답변은 유용 할 수 있지만 실제로는 문제를 해결하지 못합니다. 구현에 따라 소위 지연은 미래 또는 약속입니다.
awdz9nld

@ MartinKällman 당신이 맞아요! 나는 이것을 잠시 동안 다시 방문하지 않았고 조금 배웠다. 아래에 별도의 답변을 게시 할 것이지만 사람들이 사용 예제의 이점을 얻은 것처럼 보이기 때문에 남겨 두십시오.
fncomp

@ MartinKällman, 새로운 답변 작성을 고려했습니다. 그러나 OP는 실제로 약속과 연기가 무엇인지 알고 싶었습니다. 그의 실제 질문에 대한 대답은 대략 "지연된 자들은 스스로 해결할 수있다"는 것이다. AFAIK, 약속과 연기 된 이론은 [Functional Reactive Programming | haskell.org/haskellwiki/Functional_Reactive_Programming] 에서 유래 한 것으로 콜백을 평탄화하는 기술이다 "
fncomp

2
이것은 완전히 잘못되었으며 예제는 콜백과 마찬가지로 쉽습니다. 약속은 콜백 집계 및 디커플링에 관한 것이 아니라 동기화 코드와 같은 비동기 코드를 작성하기 위해 DSL을 제공하는 것입니다. 특히 fn(callback, errback)더 밀접하게 결합되거나 유용 fn().then(callback, errback)하지는 않지만 어쨌든 약속을 사용하는 잘못된 방법입니다. 나는 특히화물 컬트 $.when예제를 싫어합니다 $.when. 콜백과 함께 작동 하는 함수를 가질 수없는 이유는 없습니다 .
Esailija

콜백 지옥이 무엇인지 알 수 있다는 +1이지만 질문에 대답하지 않습니다.
Bhojendra Rauniyar

146

선택한 답변을 포함하여이 대답은, 개념적으로 약속을 도입,하지만 정확히 차이 (거기를 구현하는 라이브러리를 사용할 때 발생하는 용어 무엇인지 구체적인 부족을 위해 좋은 입니다 중요한 차이점).

여전히 진화하는 spec 이므로 답은 현재 wikipedia 와 같은 참조 와 jQuery 와 같은 구현을 모두 조사하려고 시도한 결과입니다 .

  • Deferred : 널리 알려진 참고 문헌, 1 2 3 4에 설명되어 있지는 않지만 구현에서 약속 해결의 중재자 (구현 및 ) 로 일반적으로 사용됩니다 . 5 6 7 resolvereject

    때로는 deferreds는 (이행 약속도 있습니다 then), (5) (6) 더 순수한으로 볼 수있어 다른 배 이연 해상도의 수 및 액세스에 대한 사용자 사용에 대한 약속을 강요 한 것으로는 . 7 then

  • 약속 : 논의중인 전략에 대한 가장 포괄적 인 단어.

    우리가 추상화하고자하는 목표 함수의 결과를 저장하고, then다른 목표 함수를 받아들이고 새로운 약속을 반환하는 함수를 노출시키는 프록시 객체 . 2

    CommonJS의 예 :

    > asyncComputeTheAnswerToEverything()
        .then(addTwo)
        .then(printResult);
    44

     

    책임 해결에 속하는 사람을 지정하지는 않았지만 항상 널리 알려진 참조에 설명되어 있습니다. 1 2 3 4

    항상 널리 사용되는 구현에 존재하며 해결 능력이 주어지지 않습니다. 5 6 7

  • 미래 : 일부 인기있는 참고 문헌 1 과 적어도 하나의 인기있는 구현에서 발견 된 겉보기가 더 이상 사용되지 않는 용어 8 , 그러나 '약속' 3 이라는 용어에 대한 선호도가 토론에서 단계적으로 폐지 된 것으로 보이며 항상 주제에 대한 대중적인 소개에서 언급되지는 않습니다. 9

    그러나 최소한 하나의 라이브러리는 일반적으로 then기능을 제공하지 않으면 서 동기화 및 오류 처리를 추상화하기 위해 일반적으로이 용어를 사용합니다 . 10 '약속'이라는 용어를 피하는 것이 의도적 인 것인지는 확실하지 않지만 약속은 'Thenables'를 중심으로하기 때문에 좋은 선택 일 것입니다. 2

참고 문헌

  1. 약속과 선물에 관한 위키 백과
  2. 약속 / A + 사양
  3. 약속에 대한 DOM 표준
  4. DOM 표준 약속 사양 WIP
  5. DOJO 툴킷 연기
  6. jQuery 연기
  7. 미래 JS
  8. 약속에 관한 기능적 JavaScript 섹션
  9. AngularJS 통합 테스트의 미래

잠재적으로 혼란스러운 것들


5
"미래"라는 용어를 좀 더 명확하게 설명하기 위해, 선물은 80 년대 중반으로 거슬러 올라가는 많은 프로그래밍 언어에서 오랜 역사를 가지고 있습니다. 그리고이 용어는 오늘날 특히 JVM에서 여전히 널리 사용되고 있습니다. JavaScript는 "Promise"라는 용어를 사용하여 Java가 "Future"의 의미와 유사한 것을 의미하는 것으로 보입니다. Scala는 동일한 개념을 "Future"와 "Promise"로 분리하여 JavaScript 프로그래머가 Promise라고 부르는 "읽기"핸들과 "쓰기"핸들을 나타냅니다.
Heather Miller

1
물론 마이크로 소프트는 그것을 위해 자신의 용어와 함께 와서 그래서 C #에서 그들이이라고하고 있었다Task
BlueRaja - 대니 Pflughoeft

72

실제로 나를 위해 클릭 한 것은 Domenic Denicola의 프레젠테이션 이었습니다.

A의 github의의 요점 , 그는 대부분의 같은 설명 나는, 아주 간결입니다했다 :

약속의 요점은 비동기 세계에서 기능 구성과 오류 버블 링을 다시 제공하는 것입니다.

다시 말해 약속은 비동기식 코드를 동기식 처럼 작성하기가 쉬운 비동기식 코드를 작성할 수있는 방법입니다 .

약속과 함께이 예를 고려하십시오.

getTweetsFor("domenic") // promise-returning async function
    .then(function (tweets) {
        var shortUrls = parseTweetsForUrls(tweets);
        var mostRecentShortUrl = shortUrls[0];
        return expandUrlUsingTwitterApi(mostRecentShortUrl); // promise-returning async function
    })
    .then(doHttpRequest) // promise-returning async function
    .then(
        function (responseBody) {
            console.log("Most recent link text:", responseBody);
        },
        function (error) {
            console.error("Error with the twitterverse:", error);
        }
    );

이 동기 코드를 작성하는 것처럼 작동합니다.

try {
    var tweets = getTweetsFor("domenic"); // blocking
    var shortUrls = parseTweetsForUrls(tweets);
    var mostRecentShortUrl = shortUrls[0];
    var responseBody = doHttpRequest(expandUrlUsingTwitterApi(mostRecentShortUrl)); // blocking x 2
    console.log("Most recent link text:", responseBody);
} catch (error) {
    console.error("Error with the twitterverse: ", error);
}

(여전히 복잡하게 들리면 프레젠테이션을보십시오!)

연기에 관해서는, 그것은 방법 .resolve()또는 .reject()약속입니다. 에서 약속 / B의 스펙, 그것은이라고합니다 .defer(). jQuery에서는 $.Deferred()입니다.

내가 아는 한 jQuery 1.8.2에서 jQuery의 Promise 구현이 중단되었습니다 (요점 참조).
아마도 Promises / A thenables 구현 하지만 전체 "비동기 시도 / 캐치"기능이 작동하지 않는다는 점에서 올바른 오류 처리를 얻지 못합니다. 비동기 코드와 함께 "try / catch"를 사용하는 것이 정말 멋지므로 유감입니다.

약속을 사용하려면 (자신의 코드로 시도해야합니다!) Kris Kowal의 Q를 사용하십시오 . jQuery 버전은 더 깨끗한 jQuery 코드를 작성하기위한 콜백 애그리 게이터 일뿐입니다.

미래에 관해서는, 나는 어떤 API에서도 그것을 보지 못했습니다.

편집 : 약속에 Domenic Denicola의 유튜브 이야기 에서 @Farm 아래의 코멘트.

비디오 에서 Michael Jackson (예, Michael Jackson ) 의 인용문 :

나는 당신이이 문구를 당신의 마음 속에 태우 길 원합니다. 약속은 비동기적인 가치 입니다.

이것은 훌륭한 설명입니다. 약속은 미래의 변수와 같습니다-어떤 시점에서 존재하거나 일어날 일에 대한 일류 참조.


5
W3 및 Chrome 핵심 팀 구성원이 제공하는 선물 (현재 DOM에 구현 됨)에 대한 자세한 설명은 여기에서 찾을 수 있습니다. xanthir.com/b4PY0
oligofren

1
@oligofren 링크 주셔서 감사합니다, 좋은 것 같습니다! 그건 그렇고, 신비한 성가신 파비콘 롤.
Camilo Martin

1
이 답변에는 더 많은 투표가 필요합니다. 허용 된 답변 IMO보다 높은 순위로 투표해야합니다.
Chev

1
약속에 관한 Domenic Denicola의 YouTube 이야기 : youtube.com/watch?v=hf1T_AONQJU
Farm

@ 농장 위대한! 답변에 추가하겠습니다.
Camilo Martin

32

약속은 약속이 만들어 질 때 값에 대한 프록시가 반드시 알려진 나타냅니다. 핸들러를 비동기 조치의 최종 성공 값 또는 실패 이유에 연관시킬 수 있습니다. 이를 통해 비동기 메소드는 동기 메소드와 같은 값을 리턴 할 수 있습니다. 최종 값 대신 비동기 메소드는 미래의 어느 시점에서 값을 가질 가능성을 리턴합니다.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

deferred.promise()메소드는 비동기 함수가 다른 코드가 내부 요청의 진행 또는 상태를 방해하지 않도록합니다. Promise는 추가 처리기를 연결하거나 상태 (결정 , 완료, 실패, 항상, 파이프, 진행 상태, 상태 및 약속 )를 결정하는 데 필요한 지연된 메소드 만 노출 하지만 상태를 변경하는 것은 아닙니다 ( resolve, reject, notify, resolveWith, rejectWith 및 notifyWith ).

대상이 제공되면 deferred.promise()메소드를 첨부 한 다음 새 오브젝트를 작성하지 않고이 오브젝트를 리턴합니다. 이미 존재하는 개체에 Promise 동작을 연결하는 데 유용 할 수 있습니다.

지연을 작성하는 경우 특정 시점에서 해결되거나 거부 될 수 있도록 지연에 대한 참조를 유지하십시오. 다른 코드가 콜백을 등록하거나 현재 상태를 검사 할 수 있도록 deferred.promise ()를 통해 Promise 객체 만 반환합니다.

간단히 말해 약속 은 아직 연기 되지 않은 작업을 나타내는 것으로 아직 알려지지 않은 값을 나타낼 수 있습니다 .


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


1
차트 표시에 1을 더한 값입니다. 브라 비 시모 !! ^ _ ^
Ashok MA

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.