Promise可以有多个 onFulfilled 参数吗?

IT技术 javascript promise
2021-01-22 07:18:51

我在这里遵循规范,我不确定它是否允许使用多个参数调用 onFulfilled。例如:

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

这样我的代码:

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

会同时收到arg1arg2?

我不关心任何特定的Promise实现是如何做到的,我希望密切关注 w3c 的Promise规范。

6个回答

我在这里遵循规范,我不确定它是否允许使用多个参数调用 onFulfilled。

不,只有第一个参数将被视为Promise构造函数中的解析值。您可以使用复合值(如对象或数组)进行解析。

我不关心任何特定的Promise实现是如何做到的,我希望密切关注 w3c 的Promise规范。

这就是我相信你错的地方。该规范被设计为最小的,并且是为 Promise 库之间的互操作而构建的。这个想法是拥有一个子集,例如 DOM 期货可以可靠地使用并且库可以使用。Promise 实现现在可以满足您的要求.spread例如:

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

蓝鸟如果您想要此功能,一种解决方案是对其进行 polyfill。

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);    
});

用原生的Promise放心地拨弄或者使用现在(2018)在浏览器中司空见惯的传播:

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

或等待:

let [a, b, c] = await Promise.resolve(['hello', 'world', '!']);
请注意,其他库(如 Q)也支持.spreadBluebird - 它不在规范中的原因是保持规范最小对于允许代码和库之间的互操作来说确实很重要
2021-03-15 07:18:51
第二个注意事项 - 您可能希望Promise.all在应用函数之前调用数组,而不是仅仅使用.then它来处理提供的一些糖库。这不是强制性的,但很可爱。
2021-03-27 07:18:51
@KrisKowal 请注意, .spread() 隐式执行 .all() 但 ES6 解构语法没有 -> bluebirdjs.com/docs/api/spread.html
2021-04-05 07:18:51
spread是权宜之计。ES6 引入了解构和 rest/spread 运算符,从而消除了对spread直接的需求.then(([a, b, c]) => {})
2021-04-08 07:18:51
Promises.all 对于您的实现是强制性的,尽管您可以将实现更改为 return Promise.all(args).then(function(args){return fn.apply(this, args);})
2021-04-09 07:18:51

您可以使用 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]) => {
    // ....
});
一个例子会很好并且对这个答案有帮助
2021-03-23 07:18:51

Promise的履行值与函数的返回值平行,Promise的拒绝原因与函数抛出的异常平行。函数不能返回多个值,因此Promise不能有超过 1 个履行值。

据我所知,阅读ES6 Promise 规范标准Promise 规范没有条款阻止实现处理这种情况 - 但是它没有在以下库中实现:

我认为他们省略 multi arg resolves 的原因是为了使更改顺序更简洁(即,因为您只能在函数中返回一个值,这会使控制流程不那么直观)示例:

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);
});
Q 不支持多值解析,因为 promise 作为函数调用结果的代理,但也可以代理远程对象。在这两种情况下,数组是复合值的唯一合理表示。通过在 ES6 中添加解构和“扩展”参数,语法变得非常好。“传播”方法是权宜之计。
2021-03-16 07:18:51
好吧,您总是可以return Promise.of(x, y)代替then回调中的标量值
2021-03-26 07:18:51

ES6 中的解构赋值在这里会有所帮助。例如:

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