Versprechen, zusätzliche Parameter an die Kette übergeben

100

Ein Versprechen, nur zum Beispiel:

var P = new Promise(function (resolve, reject) {
  var a = 5;
  if (a) {
    setTimeout(function(){
      resolve(a);
    }, 3000);
  } else {
    reject(a);
  }
});

Nachdem wir angerufen haben, dann die Methode auf das Versprechen:

P.then(doWork('text'));

Die doWork-Funktion sieht folgendermaßen aus:

function doWork(data) {
  return function(text) {
    // sample function to console log
    consoleToLog(data);
    consoleToLog(b);
  }
}

Wie kann ich vermeiden, eine innere Funktion in doWork zurückzugeben, um Zugriff auf Daten aus den Versprechungs- und Textparametern zu erhalten? Gibt es irgendwelche Tricks, um die innere Funktion zu vermeiden?

user3110667
quelle
1
Warum sollte jemand absichtlich auf Curry verzichten ? Um die abscheuliche bindMethode anzuwenden ? - was auch extrem langsam ist.
@ftor Ich verstehe dich nicht, kannst du bitte einen Code zur Klarstellung angeben?
Roland

Antworten:

86

Sie können Function.prototype.bindeine neue Funktion mit einem Wert erstellen, der wie folgt an das erste Argument übergeben wird

P.then(doWork.bind(null, 'text'))

und Sie können ändern doWorkzu,

function doWork(text, data) {
  consoleToLog(data);
}

Jetzt textwird tatsächlich 'text'in doWorkund datawird der Wert durch das Versprechen gelöst.

Hinweis: Stellen Sie sicher, dass Sie Ihrer Versprechenskette einen Ablehnungshandler hinzufügen.


Arbeitsprogramm: Live-Kopie auf Babels REPL

function doWork(text, data) {
  console.log(text + data + text);
}

new Promise(function (resolve, reject) {
    var a = 5;
    if (a) {
      setTimeout(function () {
        resolve(a);
      }, 3000);
    } else {
      reject(a);
    }
  })
  .then(doWork.bind(null, 'text'))
  .catch(console.error);
thefourtheye
quelle
danke, das hilft, früher versuche ich doWork.call (dies, 'text'), aber die Daten wurden durch 'text' ersetzt
user3110667
2
callRuft eine Funktion direkt auf, binderstellt eine neue Funktion, beide akzeptieren jedoch einen Ausführungskontext als erstes Argument.
sdgluck
103

Die vielleicht einfachste Antwort lautet:

P.then(function(data) { return doWork('text', data); });

Oder, da dies markiert ist ecmascript-6, mit Pfeilfunktionen:

P.then(data => doWork('text', data));

Ich finde das am lesbarsten und nicht zu viel zum Schreiben.

Ausleger
quelle
5

Verwenden Sie Curry.

var P = new Promise(function (resolve, reject) {
    var a = 5;
    if (a) {
        setTimeout(function(){
            resolve(a);
        }, 3000);
    } else {
        reject(a);
    }
});

var curriedDoWork = function(text) {
    return function(data) {
        console.log(data + text);
    }
};

P.then(curriedDoWork('text'))
.catch(
    //some error handling
);
yks
quelle
b Vorsicht, wenn Sie curriedDoWorkin return new Promise()der ersten Zeile dieser Funktion ein Versprechen erstellen , wird das Versprechen ausgeführt, sobald Sie anrufen curriedDoWork()(wie Sie es in..then(curriedDoWork('text'))
Flame
@Flame: kurze Antwort, wenn Sie möchten, können Sie das Versprechen in eine Funktion einbinden.
Germain
@yks, Sie hätten diese Syntax angeben können, die ziemlich interessant ist. const curriedWork = text => data => console.log (data + text)
deutsch
1
@germain ah ja, ich habe dieses Formular schon einmal gesehen, ich muss funktionale Programmierung lieben. Allerdings treten in einigen Browsern Pfeilfunktionen auf, daher vermeide ich dies jetzt.
yks
@yks, nur Internet Explorer unterstützt es nicht und wird es aufgrund von Edge niemals tun. Der letzte Build von Internet Explorer war der 9. Dezember 2015. Gehen wir weiter ~
Germain
0

Lodash bietet genau dafür eine gute Alternative.

 P.then(_.bind(doWork, 'myArgString', _));

 //Say the promise was fulfilled with the string 'promiseResults'

 function doWork(text, data) {
     console.log(text + " foo " + data);
     //myArgString foo promiseResults
 }

Wenn Sie möchten, dass Ihre Erfolgsfunktion nur einen Parameter enthält (die Ergebnisse des erfüllten Versprechens), können Sie ihn folgendermaßen verwenden:

P.then(_.bind(doWork, {text: 'myArgString'}));

function doWork(data) {
    console.log(data + " foo " + this.text);
    //promiseResults foo myArgString
}

Dies wird an text: 'myArgString'den thisKontext innerhalb der Funktion angehängt.

JellyRaptor
quelle