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?


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

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.


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

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.


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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.