Can Promises Have Multiple Arguments to Onfulfilled

Can promises have multiple arguments to onFulfilled?

I'm following the spec here and I'm not sure whether it allows onFulfilled to be called with multiple arguments.

Nope, just the first parameter will be treated as resolution value in the promise constructor. You can resolve with a composite value like an object or array.

I don't care about how any specific promises implementation does it, I wish to follow the w3c spec for promises closely.

That's where I believe you're wrong. The specification is designed to be minimal and is built for interoperating between promise libraries. The idea is to have a subset which DOM futures for example can reliably use and libraries can consume. Promise implementations do what you ask with .spread for a while now. For example:

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

With Bluebird. One solution if you want this functionality is to polyfill it.

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

This lets you do:

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

With native promises at ease fiddle. Or use spread which is now (2018) commonplace in browsers:

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

Or with await:

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

Resolving a promise to multiple parameter values

No, the Promises spec only defines the first parameter. You can't pass in others, you can only emulate it using destructuring or spreads.

From the Promises/A+ spec, 2.2.2.1, emphasis mine:

If onFulfilled is a function:

  • it must be called after promise is fulfilled, with promise’s value as its first argument.

The ES6 spec describes this in NewPromiseReactionJob (27.2.2.1) step 1.e:

e. Else, let handlerResult be Completion(HostCallJobCallback(handler, undefined, « argument »)).

In both cases the spec allows a single Promise handler value. Unlike features like setTimeout where additional arguments can be passed to the handler, there is no such option for Promises.

You can at least avoid repeating the argument list with spread syntax:

Promise.resolve()
.then(providesThreeValues)
.then(threeValues => takesThreeParameters(...threeValues))
.then(console.log);

Likewise, if you are willing to edit the function, the edit to takesThreeParameters could be minimal with array destructuring:

function takesThreeParameters ([a, b, c]) {  // new brackets
console.log(`${a} ${b} ${c}`);
return 'something';
}

How do you properly return multiple values from a Promise?

You can't resolve a promise with multiple properties just like you can't return multiple values from a function. A promise conceptually represents a value over time so while you can represent composite values you can't put multiple values in a promise.

A promise inherently resolves with a single value - this is part of how Q works, how the Promises/A+ spec works and how the abstraction works.

The closest you can get is use Q.spread and return arrays or use ES6 destructuring if it's supported or you're willing to use a transpilation tool like BabelJS.

As for passing context down a promise chain please refer to Bergi's excellent canonical on that.

How to resolve JS Promises with multiple values between parenthesis?

You can only send a single value, consider sending as an array and spreading it at the reciever

new Promise((resolve, reject) => {
return reject(new Error('no bears'));
setTimeout(() => {
resolve(['Bears', 'Lions', 'Tigers'])
}, 1000);
})
.then(quote => {
console.log(...quote); // spreads to 3 items
})

Resolve multiple promises within for loops before continuing

There is Promise.all to await multiple promises.

So what you need to do is to create an array of generateCanvasFromHtml() executions from pdfComponents and feed this array to Promise.all.



Related Topics



Leave a reply



Submit