Javascript:水平链接承诺没有多个然后调用

时间:2017-10-16 03:21:39

标签: javascript

是否有一种简短的内置方式来进行水平承诺链接?

连锁步骤的常用方法是:

(async()=>1)().then(_=>{
  //etc..
  return _+_
}).then(_=>{
  //etc..
  return _*_
}).then(_=>{
  //etc..
  return alert(_) // alert 4
})

所以我使用助手避免重复then

F=(...args)=>{
  let p=args[0]
  for(let x=1; x<args.length;++x){
    p=p.then(args[x])
  }
}

F((async()=>1)(), _=>{
  //etc..
  return _+_
}, _=>{
  //etc..
  return _*_
}, _=>{
  //etc..
  return alert(_)
})

另一种变形,它重载原型并允许第二个参数:

Promise.prototype.thenAll = function(...args){
  let p = this;
  args.forEach(_=>p=p.then(_[0], _[1]))
}

;(async()=>1)().thenAll([_=>{
  //etc..
  return _+_
}], [_=>{
  //etc..
  return _*_
}], [_=>{
  //etc..
  return alert(_)
}])

但是,有没有一种内置的方法来做类似于这些的事情?

4 个答案:

答案 0 :(得分:3)

正如其他人所说,没有内置的方法可以做到这一点。以下代码可能会引起关注。

有一个称为“提升”的概念,您可以将函数转换为处理包装值的函数。在这种情况下承诺。它看起来像这样:

const lift = (fn) => (promise) => promise.then(fn);

还有一个想法是将一系列功能链接在一起,将它们相互组合起来。像这样:

const chain = (...fns) => (value) => fns.reduce((result, fn) => fn(result), value)

这些工具允许您将代码重写为:

chain(
  lift(_=>++_),
  lift(_=>_*=_),
  lift(_=>alert(_))
)((async()=>1)())

按预期警告4。

我对你使用++__*=_感到有些困惑,因为它们意味着你希望改变变量。由于您的代码的结构如何,因此可以更好地显示使用_+1_*_

的意图

答案 1 :(得分:1)

使用Array.reduce(),您可以使用以下静态函数将一系列函数组合到一个promise链中:

&#13;
&#13;
function series (initial, ...callbacks) {
  return callbacks.reduce(
    (chain, callback) => chain.then(callback),
    Promise.resolve(initial)
  )
}

series(1, _=>_+1, _=>_*_, alert)
&#13;
&#13;
&#13;

为方便起见,您可以将其定义为Promise.series(),如下所示:

Object.defineProperty(Promise, 'series', {
  configurable: true,
  value: function series (initial, ...callbacks) { ... },
  writable: true
})

最后,在ES2017中,您也可以使用async / await来编写它:

&#13;
&#13;
async function series(initial, ...callbacks) {
  let value = await initial

  for (const callback of callbacks) {
    value = await callback(value)
  }

  return value
}

series(1, _=>_+1, _=>_*_, alert)
&#13;
&#13;
&#13;

答案 2 :(得分:1)

您可以使用rest参数将N函数传递给函数,该函数按顺序返回要调用的Promise,并将先前的Promise值设置为传递给当前函数调用的参数直到没有元素使用async/await保留在数组中并重复安排相同的过程

&#13;
&#13;
const a = n => new Promise(resolve => 
  setTimeout(resolve, Math.floor(Math.random() * 1000), ++n));

const b = n => new Promise(resolve => 
  setTimeout(resolve, Math.floor(Math.random() * 1000), n * n));

const F = async(n, ...fns) => {
  try {
    while (fns.length) n = await fns.shift()(n);
    alert(n);
  } catch (err) {
    throw err
  }
  return n
}

F(1, a, b)
.then(n => console.log(n))
.catch(err => console.error(err));
&#13;
&#13;
&#13;

答案 3 :(得分:-1)

鉴于Question的代码是同步的,您可以使用问题

中的代码

&#13;
&#13;
((_) => (_++, _*=_, alert(_)) )(1)
&#13;
&#13;
&#13;

或使用async/await

&#13;
&#13;
(async(_) => (_ = await _, _++, _ *= _, alert(_)))(Promise.resolve(1))
&#13;
&#13;
&#13;