web-dev-qa-db-de.com

Können Versprechungen mehrere Argumente für onFulfilled haben?

Ich folge der Spezifikation hier und bin mir nicht sicher, ob onFulfilled mit mehreren Argumenten aufgerufen werden kann. Zum Beispiel:

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

so dass mein Code:

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

würde beide erhalten arg1 und arg2?

Es ist mir egal, wie eine bestimmte Versprechungsimplementierung funktioniert, ich möchte die w3c-Spezifikation für Versprechungen genau befolgen.

119
badunk

Ich folge hier der Spezifikation und bin mir nicht sicher, ob onFulfilled mit mehreren Argumenten aufgerufen werden kann.

Nein, nur der erste Parameter wird im Versprechen-Konstruktor als Auflösungswert behandelt. Sie können mit einem zusammengesetzten Wert wie einem Objekt oder Array auflösen.

Es ist mir egal, wie eine bestimmte Versprechungsimplementierung funktioniert, ich möchte die w3c-Spezifikation für Versprechungen genau befolgen.

Ich glaube, du liegst falsch. Die Spezifikation ist so konzipiert, dass sie minimal ist und für die Interoperabilität zwischen Versprechen-Bibliotheken ausgelegt ist. Die Idee ist, eine Teilmenge zu haben, die beispielsweise DOM-Futures zuverlässig nutzen und Bibliotheken konsumieren können. Promise Implementierungen machen was Sie verlangen mit .spread seit einiger Zeit. Zum Beispiel:

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

Mit Bluebird . Eine Lösung, wenn Sie diese Funktionalität wünschen, ist die Polyfüllung.

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

So können Sie:

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

Mit einheimischen Versprechungen wohl Geige . Oder verwenden Sie die in Browsern heute (2018) übliche Verbreitung:

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

Oder mit erwarten:

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

Sie können die E6-Destrukturierung verwenden:

Objektdestrukturierung:

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

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

Array destructuring:

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

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

Der Erfüllungswert eines Versprechens entspricht dem Rückgabewert einer Funktion, und der Ablehnungsgrund eines Versprechens entspricht der geworfenen Ausnahme einer Funktion. Funktionen können nicht mehrere Werte zurückgeben, daher dürfen Zusagen nicht mehr als 1 Erfüllungswert enthalten.

15
Esailija

Soweit ich das Lesen der ES6 Promise-Spezifikation und der Standard-Promise-Spezifikation beurteilen kann, gibt es keine Klausel, die eine Implementierung daran hindert, diesen Fall zu behandeln - sie ist jedoch nicht in den folgenden Bibliotheken implementiert:

Ich gehe davon aus, dass der Grund für das Weglassen von Multi-Arg-Auflösungen darin besteht, die Reihenfolge prägnanter zu gestalten (d. H. Da Sie nur einen Wert in einer Funktion zurückgeben können, würde dies den Steuerungsfluss weniger intuitiv machen). Beispiel:

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

Ich suche nach der gleichen Lösung und fand etwas sehr Interessantes aus dieser Antwort: Versprechen mit mehreren Argumenten (wie $ http) in AngularJS ablehnen

die Antwort dieses Kerls 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 

Und um es zu benutzen:

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

Da Funktionen in Javascript mit einer beliebigen Anzahl von Argumenten aufgerufen werden können und das Dokument die Argumente der onFulfilled () -Methode abgesehen von der folgenden Klausel nicht einschränkt, können Sie meiner Meinung nach der onFulfilled () -Methode so lange mehrere Argumente übergeben als der Wert des Versprechens ist das erste Argument.

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

Tolle Frage und tolle Antwort von Benjamin, Kris und anderen - vielen Dank!

Ich benutze dies in einem Projekt und habe ein Modul erstellt, das auf Benjamin Gruenwalds Code basiert. Es ist auf npmjs verfügbar:

npm i -S promise-spread

Dann machen Sie in Ihrem Code

require('promise-spread');

Wenn Sie eine Bibliothek wie any-promise Verwenden

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

Vielleicht finden das auch andere nützlich!

0
AndreasPizsa

Um den folgenden Artikel in Anführungszeichen zu setzen, "" werden dann zwei Argumente verwendet, ein Rückruf für einen Erfolgsfall und ein anderes für den Fehlerfall. Beide sind optional, sodass Sie einen Rückruf nur für den Erfolgsfall oder den Fehlerfall hinzufügen können. "

Normalerweise schaue ich auf dieser Seite nach grundlegenden Versprechungsfragen. Lassen Sie mich wissen, wenn ich falsch liege

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

0