繁体   English   中英

装饰Javascript Promise.then以便参数函数接收附加参数

[英]Decorate Javascript Promise.then so that the argument function receive additional parameter

我使用ES6 Promise有以下代码:

const ctx = {}
Promise.resolve()
  .then(() => doSomethingWith(ctx))
  .then((retValue) => doSomethingElseWith(retValue, ctx))

我希望能够做到这样的事情:

const ctx = {}
using(ctx)
   .then((ctx) => doSomethingWith(ctx))
   .then((retValue, ctx) => doSomethingElseWith(retValue, ctx))

对于第一个then ,我有这样的事情:

function using(ctx) {
  const p = Promise.resolve()
  p.then = (fn) => withCtx(fn, ctx)
  return p
}

function withCtx (fn, ctx) {
  const p = new Promise((resolve) => {
    resolve(fn.apply(this, [ctx]))
  })
  return p
}

但我希望它能够处理第二种情况然后同时接受前一个承诺返回值和上下文......我怎么能有这个部分:

fn.apply(this, [ctx]) // want previous promise returned value and ctx here !

处理案例fn已经采用了我们想要传播的参数...上面描述的retValue案例。

任何想法 ? (我想要覆盖的用例是能够随时停止Promise链,在磁盘上保留值并随时从磁盘恢复更改的上下文重新启动)

说实话,我认为这是令人困惑的,可能是一种反模式,但你可以简单地通过添加一个额外的then在承诺之间传递可变状态

Promise.resolve({}) 
.then(ctx => doSomethingWith(ctx)
  .then(ret => ({ret, ctx})))
.then(({ret, ctx}) => doSomethingElseWith(ret, ctx))

第二个then在第一个内部,因此在输入状态上有一个闭包,它可以用变换后的值进行修饰,然后将变异的上下文传递给下一个阶段。 这不会泄露任何对全球背景的引用。

展示如果扩展模式的样子......

function trans (that, y) {
  console.dir(y);
  return new Promise(res =>
    setTimeout(res.bind(null, that.op(y)), 1000)
  )
}

Promise.resolve({ret: 0, ctx: {op: _ => _ + 2}})
  .then(({ret, ctx}) => trans(ctx, ret)
    .then(ret =>({ ret, ctx}))
  )
  .then(({ret, ctx}) => trans(ctx, ret)
    .then(ret =>({ ret, ctx}))
  )
  .then(({ret, ctx}) => trans(ctx, ret)
    .then(ret =>({ ret, ctx}))
  )
  .then(({ret, ctx}) => trans(ctx, ret)
    .then(ret =>({ ret, ctx}))
  )
  .then(ctx => console.dir(ctx));
  .catch(console.log.bind(console));

以下可能是您正在寻找的模式:

something0()
  .then(result0 => something1(ctx, result0)
    .then(result1 => something2(ctx, result0, result1)
      .then(result2 => something3(ctx, result0, result1, result2))
    )
  )
;

是的,它是一种厄运的金字塔,但没有其他方法可以将以前的结果保留在以后使用的范围内。

值得记住的是,如果您需要通过计算传递多个值,那么您只需从.then函数返回多个值/结果的列表(Array):

Promise.resolve(6)
  .then( x => [x+6, x] )
  .then( ([latestVal, oldvalue]) => /*whatever*/ );

这种方法没有任何问题,还有其他各种方法(比如unapply/apply你可以用来修改你的处理函数,以便接收/使用Arrays作为返回类型(你应该把它当作嵌套类型:你是现在正在研究Promise [Array [... values]],这实际上是非常常见的模式。

请注意,即使某些值本身是从异步操作派生的,这也可以工作:只需将它们传递给Promise.all,它就会将一个值/ Promise数组转换为一个Array的Promise,然后你可以将Array解构为得到你的各种结果。

Promise.resolve(6)
  .then( x => Promise.all([additionApi(x), x]) )
  .then( ([latestVal, ...rest]) => Promise.all( additionApi(x).concat(latest, rest) ) )
  .then( ([latestVal, ...rest]) => Promise.all( additionApi(x).concat(latest, rest) ) );
  //...etc.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM