Promises,将附加参数传递给 then 链

Posted

技术标签:

【中文标题】Promises,将附加参数传递给 then 链【英文标题】:Promises, pass additional parameters to then chain 【发布时间】:2015-12-30 23:25:49 【问题描述】:

一个承诺,例如:

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

我们在 promise 上调用.then() 方法后:

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

那么doWork函数看起来是这样的:

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

如何避免在 doWork 中返回内部函数,以便从 promise 和 text 参数中访问数据?有没有什么技巧可以避开内部函数?

【问题讨论】:

为什么有人会故意放弃currying?为了使用可怕的bind 方法? - 这也非常慢。 @ftor 我不明白你,你能提供一些代码来澄清一下吗? 【参考方案1】:

也许最直接的答案是:

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

或者,因为这是标记ecmascript-6,使用箭头函数:

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

我觉得这个可读性最强,写的也不多。

【讨论】:

在您的 es6 示例和“类”中,我将如何将“文本”替换为对创建承诺时迭代的数组中的项目的引用。例如:fetch(request).then(data => this.AssetRetrieved(jData.parms[i].Value, data)); @Reahreic 这听起来像是循环问题中 JS 闭包的变体。 this answer 有用吗?如果没有,请考虑提出一个更详细的新问题。【参考方案2】:

您可以使用Function.prototype.bind 创建一个新函数,并将值传递给它的第一个参数,如下所示

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

您可以将doWork 更改为,

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

现在,textdoWork 中实际上是 'text'data 将是 Promise 解析的值。

注意:请确保将拒绝处理程序附加到您的承诺链。


工作程序: Live copy on Babel's 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' call 就地调用一个函数,bind 创建一个新函数,但是两者都接受一个执行上下文作为它们的第一个参数。【参考方案3】:

使用柯里化。

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 请注意这一点,如果您通过在此函数的第一行执行return new Promise()curriedDoWork 创建为一个promise,则该promise 在您调用curriedDoWork() 时立即执行(就像您做..then(curriedDoWork('text')) @Flame:简短的回答,为方便起见,如果您愿意,可以将承诺包装成一个函数。 @yks,你可以指出这个非常有趣的语法 const curriedWork = text => data => console.log(data + text) @germain 啊是的,我以前见过这种形式,一定喜欢函数式编程。但是我在某些浏览器中遇到箭头功能中断,所以我现在倾向于避免它。 @yks,只有 Internet Explorer 不支持它并且永远不会支持它,因为 Edge,Internet Explorer 的上一个版本是 2015 年 12 月 9 日。让我们继续吧~【参考方案4】:

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 上下文。

【讨论】:

【参考方案5】:

这个问题的新答案是使用箭头函数(它会自动绑定this 并且更具可读性)。谷歌的链接,例如: https://2ality.com/2016/02/arrow-functions-vs-bind.html

您可以将文本设置为:

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

注意:this.text 内的 doWork 将评估为“文本”。

这是上面的jib建议的,那(或这个!)现在应该是公认的答案。

【讨论】:

【参考方案6】:

使用它,以便您可以访问承诺正文中的全局变量

var ref=this;

例子

p.then((data)=>
  var ref=this;
);

【讨论】:

以上是关于Promises,将附加参数传递给 then 链的主要内容,如果未能解决你的问题,请参考以下文章

Python最小化函数:将附加参数传递给约束字典

Laravel 将附加参数传递给函数

如何将附加参数传递给 jQuery DataTable ajax 调用?

如何在不覆盖数据源参数的情况下将附加参数传递给剑道模板

角度 ngResource 将附加参数传递给 url

将附加参数传递给 jQuery each() 回调