当我开始这样的代码时
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
请帮帮我。我究竟做错了什么?
答案 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();
});