then ()에서 반환 값 또는 Promise.resolve의 차이점은 무엇입니까?


314

차이점은 무엇입니까?

new Promise(function(res, rej) {
    res("aaa");
  })
  .then(function(result) {
    return "bbb";
  })
  .then(function(result) {
    console.log(result);
  });

이:

new Promise(function(res, rej) {
    res("aaa");
  })
  .then(function(result) {
    return Promise.resolve("bbb");
  })
  .then(function(result) {
    console.log(result);
  });

체인 .then ()과 함께 Angular 및 $ http 서비스를 사용하여 다른 동작을 겪고 있습니다. 코드가 너무 많으므로 먼저 위의 예입니다.


1
어떤 "다른 행동"을보고 있습니까? 두 예제 모두 작동하고 거의 동일하게 작동해야합니다. Promise.resolve()번째 예에서 불필요하다.
JLRishe

4
@pixelbits then핸들러 에서 약속을 반환하는 것은 아무 문제가 없습니다 . 실제로 약속 스펙의 핵심 측면은 그렇게 할 수 있다는 것입니다.

이것은 임의로 중첩 된 thens 와 함께 작동합니다. 이에 대한 '다른 언어'라는 용어 then는 a map와 a flatMap입니다.
Benjamin Gruenbaum

1
줄 2에서 왜 res ( "aaa")를 호출해야합니까? 왜 "aaa"를 반환 할 수없고, Promise catch (resolve ()에 대한 catch (reject) (reject ()에 대한 예외를 잡는 것과 같은))?
Sam Liddicott

1
@SamLiddicott도 같은 질문을하지만 광산은 조금 더 복잡합니다. new Promise((res, rej) => { return fetch('//google.com').then(() => { return "haha"; }) }).then((result) => alert(result));이 코드는 중단됩니다 (영원히 해결되지는 않음). 그러나 내가 변경 return "haha";하면 return res("haha");작동하고 "haha"라고 경고합니다. fetch (). then ()이 이미 "haha"를 해결 된 약속으로 래핑하지 않았습니까?
Shaung Cheng

답변:


138

규칙은 then핸들러에있는 함수가 값을 리턴하면 약속이 해당 값으로 해석 / 거부되며 함수가 약속을 리턴하면 다음 then절은 함수가 리턴 한 약속의then 절입니다 . 그래서,이 경우, 첫 번째 예는 정상적인 순서를 내리는 thens당신이 할 때 하나가, 두 번째 예에서 약속 개체가 반환됩니다 것을 예상대로 값을 밖으로 인쇄 Promise.resolve("bbb")후 's를 인 then경우 체인 불려 가도록을 (모든 의도와 목적을 위해). 실제로 작동하는 방식은 아래에 자세히 설명되어 있습니다.

Promises / A + 사양에서 인용 :

약속 해결 절차는 약속과 값을 입력으로 취하는 추상 연산으로, 우리는로 표시합니다 [[Resolve]](promise, x). 만약 x그렇다면, x는 적어도 어느 정도는 약속처럼 행동한다는 가정하에 약속 의 상태를 채택x 하려고 시도한다 . 그렇지 않으면 값으로 약속을 이행합니다 x.

이러한 thenables의 처리는 Promises / A + 호환 then 메소드를 노출하는 한 약속 구현이 상호 운용되도록합니다. 또한 Promises / A + 구현은 부적합한 구현을 합리적인 방법으로 "어셈블리"할 수 있습니다.

여기서 주목해야 할 것은 다음 줄입니다.

x약속 이라면 그 상태를 채택하라 [3.4]

링크 : https://promisesaplus.com/#point-49


4
"상태 채택"은 then핸들러가 약속을 반환 할 때 동작을 표현하는 간결하고 유용한 방법 입니다. 스펙 참조의 ​​경우 +1

69
실제로 - 여기 사양의 관련 부분은 사실 [[Resolve]]에 두라고 then청정도와 값 때문에 기본적으로는 약속 값이 너무 랩 return "aaa"과 동일 return Promise.resolve("aaa")return Promise.resolve("aaa")동일로 return Promise.resolve(Promise.resolve("aaa"))- 해결은 더 값에 호출 나무 등이기 때문이다 한 번 이상 같은 결과를 얻습니다.
Benjamin Gruenbaum

8
@ Benjamin Gruenbaum은 어떤 경우에도 반환 "aaa"return Promise.resolve("aaa")교환이 가능 하다는 것을 의미 then합니까?
CSnerd

9
예, 그것이 정확히 의미하는 바입니다.
Benjamin Gruenbaum

118

간단히 말해서 then핸들러 함수 내에서 :

A) x값 (숫자, 문자열 등)은 언제 입니까?

  1. return x 에 해당 return Promise.resolve(x)
  2. throw x 에 해당 return Promise.reject(x)

B) x약속이 이미 정해 졌을 때 (더 이상 보류되지 않음) :

  1. return xreturn Promise.resolve(x)약속이 이미 해결 된 경우 와 같습니다 .
  2. return xreturn Promise.reject(x)약속이 이미 거부 된 경우 와 같습니다 .

C) x보류중인 약속은 언제 입니까?

  1. return x보류중인 약속을 반환하고 이후에 평가됩니다 then.

Promise.prototype.then () docs 에서이 주제에 대해 자세히 알아보십시오 .


93

두 예제 모두 거의 동일하게 동작해야합니다.

내부에 반환 된 값 then()핸들러 값은 해당 약속에서 리턴 된 약속의 해상도 값이 then()됩니다. 내부에 반환 된 값 .then 이 약속 인 경우, 약속이 반환 된 then()약속은 해당 약속의 "상태를 채택"하고 반환 된 약속과 마찬가지로 해결 / 거부됩니다.

첫 번째 예에서는 "bbb" 첫 번째 then()핸들러로 하므로 "bbb"다음 then()핸들러 로 전달됩니다 .

두 번째 예에서는 값으로 즉시 해결되는 약속을 반환합니다. "bbb" 하므로 "bbb"다음 then()처리기 로 전달됩니다 . ( Promise.resolve()여기서는 무관합니다).

결과는 같습니다.

실제로 다른 행동을 나타내는 예를 보여 주면 그 이유가 무엇인지 알려줄 수 있습니다.


1
좋은 대답입니다! 무엇에 대한 Promise.resolve();return;?
FabianTe

2
@FabianTe 이것 undefined대신을 제외하고는 같은 효과 가 "bbb"있습니다.
JLRishe

51

당신은 이미 좋은 정답을 얻었습니다. 나는 짧은 것을 추가해야한다고 생각했다.

다음은 Promises / A + 약속 과 동일 합니다.

  • 호출 Promise.resolve(귀하의 Angular 경우 $q.when)
  • promise 생성자를 호출하고 리졸버를 해결합니다. 귀하의 경우에는입니다 new $q.
  • then콜백 에서 값을 반환합니다 .
  • 값이있는 배열에서 Promise.all을 호출 한 다음 해당 값을 추출하십시오.

따라서 다음은 약속 또는 일반 가치 X에 대해 동일합니다.

Promise.resolve(x);
new Promise(function(resolve, reject){ resolve(x); });
Promise.resolve().then(function(){ return x; });
Promise.all([x]).then(function(arr){ return arr[0]; });

약속 사양은 Promise Resolution Procedure 를 기반으로하여 라이브러리 간의 상호 운용 ($ q 및 기본 약속 등)을 용이하게하고 인생을 전반적으로 편하게 만듭니다. 약속 해결이 발생할 때마다 전체 일관성을 생성하는 해결이 발생합니다.


내가 무슨 요점을 물어 봐도 Promise.resolve().then(function(){ return x; });될까요? 비슷한 것을하는 것을 발견했습니다 ( then블록 내부의 함수라고 함 ). 타임 아웃을하는 것과 다소 비슷하다고 생각했지만 조금 더 빠릅니다. jsben.ch/HIfDo
Sampgun

99.99 %의 경우 Promise.resolve (x)와 동일하다는 점은 없습니다. (0.001 %는 예외를 발생 with시키는 x속성 접근자를 사용 하여 객체 또는 프록시를 차단하고 있다는 것입니다.이 경우 Promise.resolve (x)는 오류가 발생하지만 Promise.resolve().then(function(){ return x; });오류가 발생하므로 거부 된 약속이됩니다. 에서 then).
Benjamin Gruenbaum

당신은 빈 공세를 연결하거나 저장하지 않았습니다. 어쨌든 나는 진술의 차이점에 대해 이야기하지 않았습니다. 내가 쓴 것에 대해 정확히 이야기하고있었습니다. 더 명확히하기 위해, 이것은 내가 이야기 한 스 니펫 if (validator) { Promise.resolve().then(() => { this._cdRef.markForCheck(); }); }입니다. 여기서 약속은 할당되지 않았으므로 요점은 무엇입니까? 타임 아웃이 같은 효과를 낼까요?
Sampgun

1
모든 동기 코드가 발생한 후이지만 I / O가 발생하기 전에 비동기 적으로 호출을 수행합니다. 이를 "마이크로 틱 시맨틱"이라고합니다.
벤자민 그렌 바움

1

유일한 차이점은 할 때 불필요한 약속을 만들고 있다는 것 return Promise.resolve("bbb")입니다. onFulfilled()처리기 에서 약속을 반환하면 약속 해결이 시작됩니다 . 이것이 약속 체인이 작동하는 방식입니다.

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