Обещания, передайте дополнительные параметры в цепочку

101

Обещание, например:

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

После вызова метод в обещании:

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

Функция doWork выглядит так:

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

Как я могу избежать возврата внутренней функции в doWork, чтобы получить доступ к данным из обещания и текстовых параметров? Есть ли какие-нибудь уловки, чтобы избежать внутренней функции?

user3110667
источник
1
Почему кто-то намеренно отказывался от каррирования ? Для того, чтобы использовать отвратительный bindметод? - что также очень медленно.
@ftor Я вас не понимаю, не могли бы вы предоставить код для пояснения?
Роланд

Ответы:

87

Вы можете использовать Function.prototype.bindдля создания новой функции со значением, переданным ее первому аргументу, например

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

и вы можете изменить doWorkна,

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

Теперь textбудет фактически 'text'в doWorkи dataбудет значение, разрешенное Promise.

Примечание. Убедитесь, что вы прикрепили обработчик отклонения к цепочке обещаний.


Рабочая программа: Живая копия на Вавилонском 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);
четыре глаза
источник
спасибо, это помогает, раньше я пробовал doWork.call (this, 'text'), но данные были заменены на 'text'
user3110667 02
2
callвызывает функцию на месте, bindсоздает новую функцию, однако оба принимают контекст выполнения в качестве своего первого аргумента.
sdgluck 02
103

Возможно, самый простой ответ:

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

Или, поскольку это помечено ecmascript-6, с помощью стрелочных функций:

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

Я считаю это наиболее читаемым, и писать не так уж много.

кливер
источник
5

Используйте каррирование.

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
источник
b будьте осторожны с этим, если вы создаете curriedDoWorkобещание, выполняя return new Promise()в первой строке этой функции, обещание выполняется, как только вы вызываете curriedDoWork()(как вы это делаете в..then(curriedDoWork('text'))
Flame
@Flame: короткий ответ, для вашего удобства вы можете обернуть обещание в функцию, если хотите.
germain
@yks, вы могли бы указать этот довольно интересный синтаксис const curriedWork = text => data => console.log (data + text)
germain
1
@germain ах да, я видел эту форму раньше, мне нужно функциональное программирование. Однако в некоторых браузерах у меня ломаются функции стрелок, поэтому сейчас я стараюсь избегать этого.
yks 06
@yks, только Internet Explorer не поддерживает его и никогда не будет, из-за Edge, последняя сборка Internet Explorer была 9 декабря 2015 года. Давайте двигаться дальше ~
germain
0

Lodash предлагает прекрасную альтернативу именно этому.

 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
 }

Или, если вы хотите, чтобы ваша функция успеха имела только один параметр (результаты выполненного обещания), вы можете использовать его следующим образом:

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

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

Это будет связано text: 'myArgString'с thisконтекстом внутри функции.

JellyRaptor
источник
0

Новый ответ на этот вопрос - использовать стрелочные функции, которые автоматически привязывают this и более удобочитаемы. Google для таких ссылок, как: https://2ality.com/2016/02/arrow-functions-vs-bind.html

Вы можете установить текст следующим образом: this.text = 'text' P.then (data => doWork (data)); //this.text внутри doWork будет оцениваться как 'text'.

Об этом свидетельствует указанная выше строчка, и этот (или такой!) Теперь должен быть принятым ответом.

Giwyni
источник