【问题标题】:Error on Bluebird spread function蓝鸟传播功能错误
【发布时间】:2017-08-31 17:00:22
【问题描述】:

当我开始这样的代码

import Promise from 'bluebird';
const mongodb = Promise.promisifyAll(require('mongodb'));
const MongoClient = mongodb.MongoClient;
MongoClient.connect(url).then((db) => {
    return Promise.all([new WorkerService(db)]);
}).spread((workerService) => (
    Promise.all([new WorkerRouter(workerService)])
)).spread((workerRouter) => {
   app.use('/worker', workerRouter);
}).then(() => {
    httpServer.start(config.get('server.port'));
}).catch((err) => {
    console.log(err);
   httpServer.finish();

});

我看错了

}).spread(function (workerService) {
   ^

TypeError: MongoClient.connect(...).then(...).spread is not a function

请帮助我。我究竟做错了什么?

【问题讨论】:

  • 显然 `MongoClient.connect(...).then(...)` 不是 Bluebird 的承诺。为什么你仍然使用.spread() 作为单个参数?而且,你为什么要使用Promise.all() 并传递一个长度为 1 的数组?这两个都很奇怪。
  • new WorkerRouter(workerService) 是否返回承诺?似乎不会,所以我不知道你为什么要把它传递给Promise.all()Promise.all() 需要一系列承诺。
  • 我怀疑“new AnythingOtherThanPromise”会返回一个 Promise
  • 既然你是新来的,让我解释一下堆栈溢出。我们正在努力帮助您,但您似乎已发布然后消失了。这并不是堆栈溢出的工作原理。这个地方比典型的互联网论坛更具互动性,您可能会在其中发布然后第二天回来查看您收到的回复。如果您在这里这样做并且未能与向您提问的人互动,那么您的问题可能会因为没有回应或不清楚而被否决。

标签: javascript ecmascript-6 promise


【解决方案1】:

我在这里看到了一些错误:

这里的根本原因是 MongoClient.connect(...).then(...) 没有返回 Bluebird 承诺,因此没有 .spread() 方法。当你用 Bluebird 承诺一个接口时,它根本不会改变现有的方法。相反,它添加了带有“Async”后缀的新方法。

所以,除非你以某种方式告诉 Mongo 只创建 Bluebird 承诺,否则

`MongoClient.connect(...).then(...)`

只会返回 Mongo 内置的任何类型的承诺。您将需要使用新的承诺方法:

MongoClient.connectAsync(...).then(...).spread(...)

我在您的代码中看到的其他一些问题:

1) Promise.all() 期望你向它传递一系列承诺。但是当你这样做时:Promise.all([new WorkerRouter(workerService)]),你传递给它一个单一对象的数组,除非该对象本身是一个承诺,否则就是错误的。

2) 在这段代码中:

}).spread((workerService) => (
    Promise.all([new WorkerRouter(workerService)])
))

您需要返回生成的 Promise 以便将其链接到链中:

}).spread((workerService) => (
    return Promise.all([new WorkerRouter(workerService)])
))

3) 但是,没有理由在单个元素数组上使用Promise.all()。如果它是一个承诺,那么就返回它。

4) 看起来您也在尝试将 Promise 用于同步代码的不同步骤。除了让事情复杂化之外,没有理由这样做:

}).spread((workerService) => (
    Promise.all([new WorkerRouter(workerService)])    
)).spread((workerRouter) => {
   app.use('/worker', workerRouter);
}).then(() => {
    httpServer.start(config.get('server.port'));
})...

可以组合成这样:

)).spread((workerService) => {
    app.use('/worker', new WorkerRouter(workerService));
    httpServer.start(config.get('server.port'));
})...

而且,可能还可以进一步压缩,因为new WorkerService(db) 也可能不会返回承诺。

5) 而且,我们无法真正说出您为什么首先尝试使用.spread()。仅当您想要将结果数组转换为多个命名参数时才有用,但您不需要结果数组(因为没有理由将 Promise.all() 与单个项目一起使用并在现代版本的 node.js,真的没有理由再使用 .spread(),因为您可以使用 ES6 破坏数组函数参数来完成与常规 .then() 相同的事情。


我并没有声称完全按照您尝试对每一行执行的操作,但您可以这样做:

import Promise from 'bluebird';
const mongodb = Promise.promisifyAll(require('mongodb'));
const MongoClient = mongodb.MongoClient;
MongoClient.connectAsync(url).then((db) => {
    let service = new WorkerService(db);
    app.use('/worker', new WorkerRouter(service));
    // since httpServer.start() is async and there's no promise returning here,
    // this promise chain will not wait for the server to start
    httpServer.start(config.get('server.port'));
}).catch((err) => {
    console.log(err);
    httpServer.finish();
});

【讨论】:

    猜你喜欢
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-25
    • 2015-11-26
    • 2015-10-01
    • 2016-09-14
    • 2016-08-29
    相关资源
    最近更新 更多