蓝鸟传播功能出错

时间:2017-04-05 21:35:12

标签: javascript ecmascript-6 promise

当我开始这样的代码时

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

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

1 个答案:

答案 0 :(得分:1)

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

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

所以,除非你以某种方式告诉Mongo只创造蓝鸟的承诺,然后

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

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

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

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

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

2)在此代码中:

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

您需要返回结果承诺,以便将其链接到链中:

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

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

4)看起来你也试图在同步代码的不同步骤中使用promises。除了让事情变得复杂之外,没有理由这样做:

}).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();
});