当中间的承诺中的承诺检查授权时,如何管道功能?

how to pipe functions, when a promise in the promise in the middle checks authorization?

我正在尝试将一些函数组合在一起:

compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));

checkAuthorization returns 检查用户是否被授权的承诺。 buildParams 接收 someRequestData,并将结果通过管道传递给 searchItem

    checkAuthorization()
      .then(() => {
            compose(
                searchItem,
                buildParams
            )(someRequestData)
    }, (e) => {
       handleError(e)
    })

我觉得还可以,但我希望有一个更优雅的外观以提高可读性,例如:

    compose(
      searchItem,
      checkAuthorization
      buildParams
    )(someRequestData)

所以会发生什么: 1)构建参数 2)检查授权 3) 搜索项目

有什么建议吗?

不,那是不可能的,因为 checkAuthorisation 不接收和传递参数。即使你会重写它来做到这一点,它仍然会很奇怪并且 reader 会假设你正在构建应该检查其授权的参数。所以不要那样做 - 你有一个非线性流,试图强迫它进入某种线性组合是不好的。

顺便说一句,我建议您在立即调用该函数时避免 compose

checkAuthorization().then(() =>
  searchItem(buildParams(someRequestData))
, e =>
   handleError(e)
);

或者也许

checkAuthorization().then( compose(searchItem, buildParams, ()=>someRequestData)
                         , handleError ); //                ^^^^ "const"

这是一个用于处理同步功能和 Promises 的组合器。看起来它可以正常维护订单:

// Async pipe try. Pass functions left to right
const pipePromises = (...fns) => x => fns.reduce((p, fn) => p.then(fn), Promise.resolve(x));
  
// functions for the test
const me = x => new Promise(function(resolve, reject) {
  setTimeout(() => resolve(x), 10)
})

const double = x => new Promise(function(resolve, reject) {
  setTimeout(() => resolve(x * 2), 30)
})

const inc = x => new Promise(function(resolve, reject) {
  setTimeout(() => resolve(x + 1), 400)
})

const log = x => { console.log('log: ', x); return x }

const syncTriple = x => x * 3; // sync function

// let's call our chain
pipePromises( 
  me, log, // 3
  double, log, // 6
  syncTriple, log, // 18 -- SYNC
  inc, log, // 19
  double, log, // 38
  inc, log, // 39
  syncTriple, log, // 117 -- SYNC
  inc, log // 118
)(3) // 3

我刚刚制作了一个 npm module 来处理优雅的 Promise 构图。 它仍处于早期阶段,但欢迎您检查代码并根据您的需要和标准对其进行更改。

基本上它提供了两种可能满足您需求的方法:

合并

使用 Promise.combine({...}),您可以通过为对象提供一系列返回 Promises 的函数并接受先前函数的结果作为输入来组合多个 Promises,如下所示:

Promise.combine({
  item: () => searchItem,
  auth: ({item}) => checkAuth,
  params: ({item, auth}) => buildParams
}).then(({item, auth, params}) => {
  // here you can do what you need
})

减少

使用 Promise.reduce([...]),您可以将 Promise 链接到一个返回 Promise 的函数数组中,并接受先前执行的 Promise 的输出作为输入:

Promise.reduce([
  () => searchItem,
  (item) => checkAuth,
  (auth) => buildParams
]).then((params) => {
  // here you can do what you need
})

请注意,在这种情况下,您将无法访问 .then() 函数中的 item,但您始终可以编写 checkAuth Promise 的结果,以便通过item 下游也是:

Promise.reduce([
  () => searchItem,
  (item) => checkAuth.then((auth) => {
      return {auth, item}
  }),
  ({auth, item}) => buildParams.then((params) => {
      return {params, item}
  }),
]).then(({params, item}) => {
  // here you can do what you need
})

输入

您还可以像这样从请求中添加一些输入数据:

Promise.reduce([
  (requestData) => searchItem,
  (item) => checkAuth,
  (auth) => buildParams
], requestData).then((params) => {
  // here you can do what you need
})

看到我将 requestData 作为 Promise.reduce([...], requestData) 的第二个参数传递,它作为参数传递给第一个函数。

Here you can see the functions code. 希望这会有所帮助。