Obietnice, przekazanie dodatkowych parametrów do łańcucha

100

Obietnica, na przykład:

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

Po wywołaniu metoda na obietnicy:

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

Funkcja doWork wygląda następująco:

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

Jak mogę uniknąć zwracania funkcji wewnętrznej w doWork, aby uzyskać dostęp do danych z obietnicy i parametrów tekstowych? Czy są jakieś sztuczki, aby uniknąć funkcji wewnętrznej?

user3110667
źródło
1
Dlaczego ktoś miałby celowo wyrzec się curry ? Żeby użyć ohydnej bindmetody? - co również jest bardzo wolne.
@ftor Nie rozumiem cię, czy możesz podać kod do wyjaśnienia?
Roland

Odpowiedzi:

86

Możesz użyć Function.prototype.binddo stworzenia nowej funkcji z wartością przekazaną do jej pierwszego argumentu, w ten sposób

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

i możesz zmienić doWorkna,

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

Teraz textbędzie 'text'w rzeczywistości doWorki databędzie wartością ustaloną przez Obietnicę.

Uwaga: upewnij się, że dołączasz moduł obsługi odrzucania do łańcucha obietnic.


Program roboczy: kopia na żywo na REPL 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);
na czworo
źródło
dzięki, to pomaga, wcześniej próbowałem doWork.call (this, 'text'), ale dane zostały zastąpione przez 'text'
user3110667
2
callwywołuje funkcję w miejscu, bindtworzy nową funkcję, jednak oba akceptują kontekst wykonania jako pierwszy argument.
sdgluck
103

Być może najprostsza odpowiedź brzmi:

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

Lub, ponieważ jest to oznaczone ecmascript-6, za pomocą funkcji strzałkowych:

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

Uważam to za najbardziej czytelne i nie za dużo do pisania.

wysięgnik
źródło
5

Użyj 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
źródło
b uważaj na to, jeśli utworzysz curriedDoWorkobietnicę, wykonując return new Promise()w pierwszej linii tej funkcji, obietnica zostanie wykonana natychmiast po wywołaniu curriedDoWork()(tak jak robisz to w..then(curriedDoWork('text'))
Flame
@Flame: krótka odpowiedź, dla Twojej wygody możesz zawrzeć obietnicę w funkcji, jeśli chcesz to zrobić.
Germain
@yks, mogłeś wskazać tę składnię, która jest dość interesująca const curriedWork = text => data => console.log (dane + tekst)
germain
1
@germain ah tak, widziałem już ten formularz, muszę pokochać programowanie funkcjonalne. Jednak w niektórych przeglądarkach funkcje strzałek nie działają, więc teraz staram się tego unikać.
yks
@yks, tylko Internet Explorer go nie obsługuje i nigdy nie będzie, z powodu Edge, ostatnia kompilacja Internet Explorera była 9 grudnia 2015. Przejdźmy dalej ~
germain
0

Lodash oferuje fajną alternatywę właśnie w tym przypadku.

 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
 }

Lub, jeśli chcesz, aby Twoja funkcja sukcesu miała tylko jeden parametr (spełnienie obietnicy), możesz wykorzystać ją w ten sposób:

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

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

Spowoduje to dołączenie text: 'myArgString'do thiskontekstu w funkcji.

JellyRaptor
źródło
0

Nową odpowiedzią na to pytanie jest użycie funkcji strzałkowych, które automatycznie wiążą „to” i są znacznie bardziej czytelne. Google dla linków, takich jak: https://2ality.com/2016/02/arrow-functions-vs-bind.html

Możesz ustawić tekst w następujący sposób: this.text = 'text' P.then (data => doWork (data)); //this.text wewnątrz doWork oceni jako „tekst”.

Sugeruje to jib powyżej i to (lub to!) Powinno być teraz akceptowaną odpowiedzią.

giwyni
źródło