web-dev-qa-db-fra.com

Les promesses peuvent-elles avoir plusieurs arguments à onFulfilled?

Je suis la spécification ici et je ne suis pas sûr que cela permette à onFulfilled d'être appelé avec plusieurs arguments. Par exemple:

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

tel que mon code:

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

recevrait à la fois arg1 et arg2?

Peu m'importe la manière dont les promesses spécifiques sont mises en œuvre, je souhaite suivre de près les spécifications du W3C relatives aux promesses.

119
badunk

Je suis la spécification ici et je ne suis pas sûr que cela permette à onFulfilled d'être appelé avec plusieurs arguments.

Non, seul le premier paramètre sera traité comme une valeur de résolution dans le constructeur de la promesse. Vous pouvez résoudre avec une valeur composite telle qu'un objet ou un tableau.

Peu m'importe la manière dont les promesses spécifiques sont mises en œuvre, je souhaite suivre de près les spécifications du W3C relatives aux promesses.

C'est là que je crois que tu as tort. La spécification est conçue pour être minimale et est conçue pour l'interopérabilité des bibliothèques de promesses. L'idée est de disposer d'un sous-ensemble que les futurs DOM peuvent par exemple utiliser de manière fiable et que les bibliothèques peuvent consommer. Les implémentations de Promise font ce que vous demandez avec .spread pendant un moment. Par exemple:

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

Avec Bluebird . Une solution si vous voulez cette fonctionnalité est de la polyfiller.

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

Cela vous permet de faire:

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

Avec des promesses natales à l'aise violon . Ou utilisez la propagation qui est maintenant (2018) courante dans les navigateurs:

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

Ou avec attendre:

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

Vous pouvez utiliser la déstructuration E6:

déstructuration de l'objet:

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

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

déstructuration du tableau:

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

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

La valeur d'exécution d'une promesse est parallèle à la valeur de retour d'une fonction et la raison de rejet d'une promesse est parallèle à l'exception levée d'une fonction. Les fonctions ne peuvent pas renvoyer plusieurs valeurs. Les promesses ne doivent pas avoir plus d'une valeur d'exécution.

15
Esailija

Autant que je sache, les spécification de la promesse ES6 et la spécification de la promesse standard n'y a pas de clause empêchant une implémentation de gérer ce cas - cependant, elle n'est pas implémentée dans les bibliothèques suivantes:

Je suppose que la raison pour laquelle ils omettent la résolution de plusieurs arguments est de rendre l’ordre de changement plus succinct (c’est-à-dire que vous ne pouvez renvoyer qu’une valeur dans une fonction, le flux de contrôle deviendrait moins intuitif). Exemple:

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

Je cherche la même solution et je trouve quelque chose de très intéressant dans cette réponse: Rejetant les promesses avec plusieurs arguments (comme $ http) dans AngularJS

la réponse de ce gars 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 

Et pour l'utiliser:

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

Puisque les fonctions en Javascript peuvent être appelées avec un nombre quelconque d'arguments, et que le document ne place aucune restriction sur les arguments de la méthode onFulfilled () en plus de la clause below, je pense que vous pouvez transmettre plusieurs arguments à la méthode onFulfilled () aussi longtemps comme la valeur de la promesse est le premier argument.

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

Excellente question et excellente réponse de Benjamin, Kris et autres - merci beaucoup!

J'utilise cela dans un projet et j'ai créé un module basé sur code de Benjamin Gruenwald . Il est disponible sur npmjs:

npm i -S promise-spread

Puis dans votre code, faites

require('promise-spread');

Si vous utilisez une bibliothèque telle que any-promise

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

Peut-être que d'autres trouvent cela utile aussi!

0
AndreasPizsa

Pour citer l'article ci-dessous, "" then "prend deux arguments, un rappel pour un cas de réussite et un autre pour le cas d'échec. Les deux sont facultatifs, vous pouvez donc ajouter un rappel pour le cas de réussite ou d'échec uniquement."

Je regarde habituellement cette page pour des questions de base sur les promesses, laissez-moi savoir si je me trompe

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

0