Promesses, passer des paramètres supplémentaires pour ensuite enchaîner

100

Une promesse, juste par exemple:

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

Après avoir appelé, puis la méthode sur la promesse:

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

La fonction doWork ressemble à ceci:

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

Comment éviter de renvoyer une fonction interne dans doWork, pour accéder aux données des paramètres de promesse et de texte? Y a-t-il des astuces pour éviter la fonction intérieure?

user3110667
la source
1
Pourquoi quelqu'un renoncerait-il intentionnellement au curry ? Pour utiliser la bindméthode hideuse ? - qui est également extrêmement lent.
@ftou je ne vous comprends pas, pouvez-vous s'il vous plaît fournir un code pour clarification?
Roland

Réponses:

86

Vous pouvez utiliser Function.prototype.bindpour créer une nouvelle fonction avec une valeur passée à son premier argument, comme ceci

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

et vous pouvez changer doWorkpour,

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

Maintenant, textsera réellement 'text'dans doWorket datasera la valeur résolue par la promesse.

Remarque: veuillez vous assurer que vous attachez un gestionnaire de refus à votre chaîne de promesse.


Programme de travail: Live copy sur le REPL de Babel

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
la source
merci, cela aide, plus tôt j'essaye doWork.call (ceci, 'texte'), mais les données ont été remplacées par 'texte'
user3110667
2
callinvoque une fonction sur place, bindcrée une nouvelle fonction, mais les deux acceptent un contexte d'exécution comme premier argument.
sdgluck
103

La réponse la plus simple est peut-être:

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

Ou, puisque ceci est étiqueté ecmascript-6, en utilisant les fonctions fléchées:

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

Je trouve cela très lisible et pas trop à écrire.

foc
la source
5

Utilisez le 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
la source
b attention, si vous créez curriedDoWorkune promesse en faisant return new Promise()sur la première ligne de cette fonction, la promesse est exécutée dès que vous appelez curriedDoWork()(comme vous le faites dans..then(curriedDoWork('text'))
Flame
@Flame: réponse courte, pour votre commodité, vous pouvez envelopper la promesse dans une fonction, si vous le souhaitez.
germain
@yks, vous auriez pu indiquer cette syntaxe qui est assez intéressante const curriedWork = text => data => console.log (data + text)
germain
1
@germain ah oui j'ai vu ce formulaire avant, je dois aimer la programmation fonctionnelle. Cependant, je constate que les fonctions fléchées sont interrompues dans certains navigateurs, j'ai donc tendance à l'éviter maintenant.
yks
@yks, seul Internet Explorer ne le prend pas en charge et ne le sera jamais, à cause d'Edge, la dernière version d'Internet Explorer date du 9 décembre 2015. Passons à autre chose ~
germain
0

Lodash offre une belle alternative pour cette chose exacte.

 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
 }

Ou, si vous souhaitez que votre fonction de succès n'ait qu'un seul paramètre (les résultats de la promesse remplie), vous pouvez l'utiliser de cette façon:

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

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

Cela s'attachera text: 'myArgString'au thiscontexte dans la fonction.

GeléeRaptor
la source
0

La nouvelle réponse à cette question est d'utiliser des fonctions fléchées, qui lient automatiquement le «ceci» et sont beaucoup plus lisibles. Google pour les liens tels que: https://2ality.com/2016/02/arrow-functions-vs-bind.html

Vous pouvez définir le texte comme suit: this.text = 'text' P.then (data => doWork (data)); //this.text à l'intérieur de doWork sera évalué à 'text'.

Ceci est suggéré par jib ci-dessus et cela (ou ceci!) Devrait être la réponse acceptée maintenant.

giwyni
la source