약속에 onFulfilled에 대한 여러 가지 주장이있을 수 있습니까?


127

여기에 있는 사양을 따르고 있으며 onFulfilled를 여러 인수로 호출 할 수 있는지 확실하지 않습니다. 예를 들면 다음과 같습니다.

promise = new Promise(function(onFulfilled, onRejected){
    onFulfilled('arg1', 'arg2');
})

내 코드는 다음과 같습니다.

promise.then(function(arg1, arg2){
    // ....
});

모두받을 arg1과를 arg2?

구체적인 약속 구현이 어떻게 수행되는지는 신경 쓰지 않고 w3c 사양을 따르고 싶습니다.


힌트로, github.com/then/promise (베어 본 구현)를 사용하면 실제로 두 번째 인수를 제공하지 않음을 알 수 있습니다
badunk

2
.spread와 함께 Bluebird를 사용하려고합니다. -또한 스펙에 대한 관심을 멈추십시오. 스펙은 구현 간의 상호 운용성 에 관한 것이며 설계 상 최소입니다.
Benjamin Gruenbaum

답변:


130

여기에있는 사양을 따르고 있으며 onFulfilled를 여러 인수로 호출 할 수 있는지 확실하지 않습니다.

아니, 첫 번째 매개 변수 만 약속 생성자의 해상도 값으로 처리됩니다. 객체 또는 배열과 같은 복합 값으로 해결할 수 있습니다.

구체적인 약속 구현이 어떻게 수행되는지는 신경 쓰지 않고 w3c 사양을 따르고 싶습니다.

그것이 내가 틀렸다고 믿는 곳입니다. 이 사양은 최소화되도록 설계되었으며 약속 라이브러리간에 상호 운용 되도록 제작되었습니다 . 아이디어는 DOM 선물이 안정적으로 사용할 수 있고 라이브러리가 소비 할 수있는 부분 집합을 갖는 것입니다. 약속의 구현은 지금 당신이 요구하는 것을 수행합니다 .spread. 예를 들면 다음과 같습니다.

Promise.try(function(){
    return ["Hello","World","!"];
}).spread(function(a,b,c){
    console.log(a,b+c); // "Hello World!";
});

블루 버드 와 함께 . 이 기능을 원하면 솔루션을 폴리 필하는 것이 좋습니다.

if (!Promise.prototype.spread) {
    Promise.prototype.spread = function (fn) {
        return this.then(function (args) {
            return Promise.all(args); // wait for all
        }).then(function(args){
         //this is always undefined in A+ complaint, but just in case
            return fn.apply(this, args); 
        });
    };
}

이를 통해 다음을 수행 할 수 있습니다.

Promise.resolve(null).then(function(){
    return ["Hello","World","!"]; 
}).spread(function(a,b,c){
    console.log(a,b+c);    
});

기본 약속으로 쉽게 바이올린 . 또는 브라우저에서 현재 (2018) 일반적인 스프레드를 사용하십시오.

Promise.resolve(["Hello","World","!"]).then(([a,b,c]) => {
  console.log(a,b+c);    
});

또는 기다리고 있습니다 :

let [a, b, c] = await Promise.resolve(['hello', 'world', '!']);

2
Q와 같은 다른 라이브러리도 .spreadBluebird와 같이 지원 합니다. 스펙에없는 이유 는 코드와 라이브러리 사이의 상호 운용을 허용하기 위해 스펙을 최소화하는 것이 실제로 큰 문제 이기 때문 입니다.
Benjamin Gruenbaum

두 번째 참고- 일부 설탕 라이브러리가 제공하는 Promise.all기능 .then을 처리하는 대신 함수를 적용하기 전에 배열 을 호출 할 수 있습니다 . 필수는 아니지만 귀엽습니다.
Benjamin Gruenbaum

1
구현을 변경할 수는 있지만 Promies.all은 필수입니다.return Promise.all(args).then(function(args){return fn.apply(this, args);})
Esailija

14
spread스톱 갭입니다. ES6에는 구조 해제 및 나머지 / 확산 연산자가 도입되어 spread완전히 필요하지 않습니다 . .then(([a, b, c]) => {})
Kris Kowal

3
@KrisKowal .spread ()는 .all ()을 암시 적으로 수행하지만 ES6
구조화

66

E6 디스트 럭처링을 사용할 수 있습니다 :

객체 파괴 :

promise = new Promise(function(onFulfilled, onRejected){
    onFulfilled({arg1: value1, arg2: value2});
})

promise.then(({arg1, arg2}) => {
    // ....
});

배열 파괴 :

promise = new Promise(function(onFulfilled, onRejected){
    onFulfilled([value1, value2]);
})

promise.then(([arg1, arg2]) => {
    // ....
});

3
이 답변에 대한 예가 좋고 도움 이 될 것입니다!
Rahul Verma

19

약속의 이행 값은 함수의 반환 값과 유사하며 약속의 거부 이유는 던져진 예외 함수와 유사합니다. 함수는 여러 값을 리턴 할 수 없으므로 약속은 두 개의 이행 값을 가져서는 안됩니다.


4

ES6 Promise 사양표준 promise 사양을 읽으면 구현 이이 경우를 처리하지 못하게하는 조항은 없지만 다음 라이브러리에서는 구현되지 않습니다.

다중 인수 해결을 생략하는 이유는 순서를 더 간결하게 만드는 것입니다 (즉, 함수에서 하나의 값만 반환 할 수 있으므로 제어 흐름이 덜 직관적입니다).

new Promise(function(resolve, reject) {
   return resolve(5, 4);
})
.then(function(x,y) {
   console.log(y);
   return x; //we can only return 1 value here so the next then will only have 1 argument
})
.then(function(x,y) {
    console.log(y);
});

8
Q는 약속이 함수 호출 결과에 대한 프록시 역할을하지만 원격 객체에 대한 프록시 역할을하기 때문에 다중 값 해상도를 지원하지 않습니다. 이 두 경우 모두 배열은 복합 값의 현명한 표현입니다. ES6에서 파괴 및 "확산"인수를 추가하면 구문이 정말 좋아집니다. "확산"방법은 스톱 갭입니다.
Kris Kowal

콜백 return Promise.of(x, y)에서 스칼라 값 대신 항상 사용할 수 then있습니다.
Bergi

2

다음은 CoffeeScript 솔루션입니다.

나는 동일한 해결책을 찾고 있었고이 답변에서 seomething이 매우 흥미로운 것을 발견했습니다 : AngularJS에서 여러 인수 (예 : $ http)로 약속 거부

이 사람 Florian 의 대답

promise = deferred.promise

promise.success = (fn) ->
  promise.then (data) ->
   fn(data.payload, data.status, {additional: 42})
  return promise

promise.error = (fn) ->
  promise.then null, (err) ->
    fn(err)
  return promise

return promise 

그리고 그것을 사용하려면 :

service.get().success (arg1, arg2, arg3) ->
    # => arg1 is data.payload, arg2 is data.status, arg3 is the additional object
service.get().error (err) ->
    # => err

해야 ->=>?
SherylHohman

1
@SherylHohman 2015 년에 이것은 ES6 구문이 아닌 CoffeeScript ( coffeescript.org/#introduction ) 로 작성되었습니다 . 간단한 화살표는 간단한 기능이었고 지방 화살표는 ES6와 거의 같습니다 (ES6 지방 화살표는 CoffeScript에서 다소 빌려온 것 같습니다).
Val Entin

@SherylHohman 원하는 경우 ECMA에서 게시물을 편집하십시오.
Val Entin

답변 주셔서 감사합니다. 이것이 커피 스크립트 솔루션임을 명확히하기 위해 편집 할 것입니다. 이를 통해 귀하의 답변은 그대로이며 CoffeeScript 코드베이스에 유용 할 수 있습니다. 그러나 귀하의 편집 제안에 감사드립니다. 1) 귀하의 솔루션 편집 / 중단 위험이있는 CoffeeScript에 익숙하지 않습니다 ;-). 2) 코드를 현대 JS로 번역하는 것은 "원래 답변의 의도"와 다른 것으로 간주되므로 '편집'검토를 통과해서는 안됩니다. 오히려 누군가가 코드를 번역하는 경향이 있다면 새로운 답변을 게시 할 수 있습니다. 이상적으로, 그들은 그들의 영감으로 귀하의 답변에 다시 연결됩니다 :-)
SherylHohman

0

벤자민, 크리스 등의 훌륭한 질문과 훌륭한 답변-많은 감사합니다!

나는 이것을 프로젝트에서 사용하고 Benjamin Gruenwald의 코드를 기반으로 모듈을 만들었습니다 . npmjs에서 사용할 수 있습니다.

npm i -S promise-spread

그런 다음 코드에서

require('promise-spread');

다음과 같은 라이브러리를 사용하는 경우 any-promise

var Promise = require('any-promise');
require('promise-spread')(Promise);

다른 사람들도이 기능을 유용하게 사용할 수 있습니다!


0

ES6에서 Destructuring Assignment가 도움이 될 것입니다.

let [arg1, arg2] = new Promise((resolve, reject) => {
    resolve([argument1, argument2]);
});

0

Javascript의 함수는 많은 수의 인수로 호출 할 수 있으며 문서는 onFulfilled()아래 절 외에도 메소드의 인수 에 제한을 두지 않기 onFulfilled()때문에 promise의 값이 첫 번째 주장.

2.2.2.1 약속의 가치를 첫 번째 주장으로하여 약속이 이행 된 후에 호출되어야한다.


-1

아래 기사에서 ""then "은 성공 사례에 대한 콜백과 실패 사례에 대한 다른 두 가지 인수를 취합니다. 둘 다 선택 사항이므로 성공 또는 실패 사례에 대해서만 콜백을 추가 할 수 있습니다."

나는 일반적으로이 페이지에서 기본적인 약속에 관한 질문을 봅니다. 제가 틀렸다면 알려주세요

http://www.html5rocks.com/en/tutorials/es6/promises/


1
new Promise그것은 잘못되었습니다, 구문 function(resolve, error)then가지고있는 동안 구문이 있습니다.then(function(arg) {
megawac

2
@megawac 그것은 실제로 잘못되었습니다-두 번 (때로는 3) 주장을 받아들입니다-그것은 다소 드문 일입니다
Benjamin Gruenbaum

@BenjaminGruenbaum afaik its.then(function(/*resolve args*/){/*resolve handler*/}, function(/*reject args*/){/*reject handler*/})
megawac

2
예, 자세히 읽으면이 답변이 주장하는 것입니다.이 질문의 맥락에서별로 유용하지는 않지만 잘못되지는 않습니다.
Benjamin Gruenbaum
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.