使用“.then”在 bluebird 中链接异步函数。什么是最好的方法?

Chaining async functions in bluebird with ".then". What is the best way?

我目前正在学习 bluebird 并想出了这段代码(使用 Express.js 和 Mongoose)来测试它:

let startServer = Promise.promisify(app.listen, app);
let connectDB =  Promise.promisify(mongoose.connect, mongoose);

startServer(3000)
  .then(() => connectDB(MongoURI))
  .catch((e) => {
    console.log('Exception ' + e);
  });

我的第一个 .then 调用中的函数只返回另一个函数。 因此我想知道,是否有办法将 connectDB 直接传递给 .then 并使其工作。像这样:

startServer(3000)
  .then(connectDB, MongoURI)
  .catch((e) => {
    console.log('Exception ' + e);
  });

Therefore I was wondering, if there is a way to pass connectDB directly to .then and make it work.

是的,这可以通过称为 currying 的东西实现(在数学家 Haskell Curry 之后)。您还会看到它被称为 partial application。基本上,您创建了一个新函数,该函数在被调用时将使用您在创建时指定的参数调用原始函数。

JavaScript 有 Function#bind 做两件事:1. 设置 this 的内容,以及 2. 柯里化。看起来您的示例并不关心 this 会是什么,因此我们可以为此使用它。

例如:

startServer(3000)
  .then(connectDB.bind(null, MongoURI))
  .catch((e) => {
    console.log('Exception ' + e);
  });

null 用于 thisArg 参数,我们实际上没有使用它。

这里有一个更简单的例子,只是为了说明:

function foo(a, b) {
  snippet.log("a = " + a);
  snippet.log("b = " + b);
}

// "Curry" 1 as the first arg
var f1 = foo.bind(null, 1);

// Call the resulting function:
f1(2); // "a = 1, b = 2"
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

它是否 可取 是另一个问题(可能是基于意见的问题)。您带有箭头功能的原件非常清晰,而且不太可能很昂贵(就内存或时间而言)。但是可能这样做,是的。


如果您希望该函数接收 this 它被调用(可能不是您的情况,但它在基于浏览器的 jQuery 事件处理程序中很常见 JavaScript),也很容易编写一个只进行柯里化而没有 this 东西 Function#bind 的函数。 有一个非常简单、未优化的示例。