蓝鸟承诺过滤器。为什么数组?

Bluebird Promise filter. Why Arrays?

看来我错过了一些关于 JS promise 的重要内容。为什么Promise的filter方法认为promise内容是Array/Iterable?是不是看起来很不直观?

这里是 Bluebird 的过滤器签名:

Promise.filter(
  Iterable<any>|Promise<Iterable<any>> input,
  function(any item, int index, int length) filterer,
  [Object {concurrency: int=Infinity} options]
) -> Promise

至少有一种语言在标准库中有 Future/Promise - Scala,Promise.filter 采用谓词和 return [=15= 往往是很合乎逻辑的] promise if content satisfied provided predicate and Rejected with some Error if not:

Promise.filter(
  <any>|Promise<any> input, 
  function (any item) predicate
) -> Promise

这是它的用法:

getUserFromDatabase()
  .filter( user => user.isEmailValid )
  .then( 
    user => { req.statusCode = 200; }  // user is okay
    err  => { req.statusCode = 404; }  // user is not okay
  )

"filtering" 在 monad 的上下文中可能意味着两种可能的直觉。 Haskell 实际上使这一点非常清楚,因为它 对此有两个不同的功能:

mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a

Direct MonadPlus equivalent of filter applicable to any MonadPlus, for example mfilter odd (Just 1) == Just 1, mfilter odd (Just 2) == Nothing

"direct equivalent" 的意思是 filter = (mfilter:: (a -> Bool) -> [a] -> [a]),即 mfilter m 实例化为 [],就像 map = fmap.

filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]

This generalizes the list-based filter function.

它甚至可以从列表推广到任何既是 Foldable 又是 Monoid 的东西,但让我们保持简单。

这两个函数都可以应用于 promises,它是 MonadPlus 的一个实例。 Scala 选择了第一个,Bluebird 选择了第二个。

那是因为 mfilter 可以在 JavaScript 中用 .then(x => { if (predicate(x)) return x else throw … }) 非常简单地实现,您甚至可以选择错误消息或对 x 应用进一步的转换相同的回调。相比之下,高效的 filterM 并不那么容易实现,但仍然非常有用并且经常需要,因此 Bluebird 将其作为集合实用工具的一部分提供 - 包括 concurrency 在这些方法中找到的选项。