首页 > 解决方案 > Fluture:将未来转换为快速全局错误处理的承诺

问题描述

我正在尝试找到一种方法,使用 Fluture 库将 Promise 转换为 Future 来实现函数式编程,使用函数式管道转换数据,然后转换回 Promise,以便我可以利用 await/async 功能。这是一个快速应用程序,我正在使用全局错误处理,如果我在未来的处理流程中捕获错误而没有在未来的处理完成后转换为承诺,我看不到如何利用端点的全局错误处理。

  1. 我这样想对吗?
  2. 如果是这样,在调用 encaseP 和后续管道代码后,如何使用下面代码中的 promise 实用程序将其转换回 promise?
  3. 有没有更好的方法来利用未来的管道,同时仍然向全局错误处理程序发送错误?
  4. 另外,如果我确实转换为一个承诺,如果我使用等待,我将来也可以访问实际值,我假设是这样吗?

抱歉,如果这是一个不好的问题,我是函数式编程和 Fluture 的新手,我正试图让我的鸭子正确对齐。

const arrayList = [];
arrayList.push({
    a: {
        b: 1,
        c: 2,
        d: 3
    }
},{
    a: {
        b: 2,
        c: 3,
        d: 3
    }
})

const findData = (arrayList) => Promise.reject(null)

let total1 = (list) => encaseP(findData)(list)
    .pipe(res => res)
    .pipe(map(x => x.map(y => ({
        a: {
            b: y.a.b + 1,
            c: y.a.c + 1,
            d: y.a.d + 1
        }
    }))))
    .pipe(promise (() => {console.log('do nothing')}) (console.log));


console.log(total1);
total1(arrayList);

当我运行上面的代码时,我收到以下错误:

internal/modules/cjs/loader.js:992 internalBinding('errors').triggerUncaughtException(^

TypeError: promise() 期望它的第一个参数是一个有效的 Future。

标签: node.jsasync-awaitpromisefunctional-programmingfluture

解决方案


我相信我已经在 Gitter中充分回答了这个问题。我将在下面总结我的回复以供将来参考。


我在您的代码中看到了一些我想解决的问题:

  1. findData: I recommend already wrapping it right there with encaseP - as early on as possible. So you'd get (arrayList) => encaseP (Promise.reject) (arrayList), which can also be written like encaseP (Promise.reject) (because the input argument is simply passed down as-is).
  2. The total1 function can now call findData directly and get back a Future.
  3. .pipe (res => res): This line actually does nothing. Here you transform res, which is a Future of an Array, into res, which is exactly the same thing. It's important to understand that pipe is just function application: https://stackoverflow.com/a/59985017/1001417
  4. .pipe (promise (() => {console.log('do nothing')}) (console.log)): When you consume a Future, the work actually starts and the consumption returns a cancellation function (or a Promise, in the case of promise (future)). You shouldn't do this inside your functions, but outside of them. I recommend reading the introduction to Fluture, especially the part about "not consuming futures". A guiding rule of thumb is that you should only see fork (or promise or any other consumption function) called at the very "edge" of your program. That's at the point where you cannot possibly pass the Future down any further to a party that'll understand it.

After removing that last line from the total1 function, so that the Future is not consumed, but returned from the function, we can consume the Future where needed. For example, an Express middleware that runs the total1 function and forwards its output to the Response would look something like:

app.get ('/total', (req, res, next) => {
  total1 (req.query.arrayList)
  .pipe (fork (next) (result => res.json ({result})))
})

Passing next as a rejection callback to fork causes Express to handle the error. This is needed for every express route that you want to use a Future inside to control async. You can use fluture-express to take away some of that boilerplate.


推荐阅读