我试图通过mongodb查询在NodeJS中做承诺。
Mongo库是它的mongod,我认为它会回报承诺。
这是我的代码:
var dbOrders = mongo(db.serverConfig.name + "/" + db.databaseName, ['orders']);
var dbClients = mongo(db.serverConfig.name + "/" + db.databaseName, ['clients']);
var promise;
if (order.Order.Nif === "") {
var newClient = {
name: order.Order.Asegurado,
ni: order.Order.Nif,//Never used..
address: order.Order.Direccion,
city: order.Order.Poblacion,
province: order.Order.Provincia,
phone: order.Order.Telefonos,
cp: order.Order.CodigoPostal
};
promise = dbClients.clients.insert(newClient).then(function (currentClient) {
log.debug('mondialParser', 'addClient', currentClient);
dbOrders.orders.insert(order.Order).then(function (orderId) {
log.debug('mondialParser', 'addOrder', orderId);
dbClients.clients.update({_id: new ObjectID(currentClient)}, {$push: {dataOrders: orderId}}).then(function () {
log.debug('assignOrder', orderId, currentClient);
});
});
});
Q.fcall(promise);
我试图 - >然后,插入客户端,插入订单,然后将订单_id分配给客户端_id。 我把log.debug,但我只能看到
log.debug('mondialParser', 'addClient', currentClient);
其他一个不称为..为什么?这是承诺的正确用法吗?还有更好的办法吗?
编辑:
其他方式:
var parseMondial = function (db, order, log) {
"use strict";
var dbOrders = mongo(db.serverConfig.name + "/" + db.databaseName, ['orders']);
var dbClients = mongo(db.serverConfig.name + "/" + db.databaseName, ['clients']);
if (order.Order.Nif === "") {
var newClient = {
name: order.Order.Asegurado,
ni: order.Order.Nif,//Never used..
address: order.Order.Direccion,
city: order.Order.Poblacion,
province: order.Order.Provincia,
phone: order.Order.Telefonos,
cp: order.Order.CodigoPostal
};
var insertClient = function () {
dbClients.clients.insert(newClient).then(function (result) {
log.debug('mondialParser', 'addClient', result);
return result;
});
};
var insertOrder = function () {
dbOrders.orders.insert(order.Order).then(function(result) {
log.debug('mondialParser', 'addOrder', result);
return result;
});
};
Q.all([insertOrder(), insertClient()]).spread(function (resultOrder, resultClient) {
dbClients.clients.update({_id: new ObjectID(resultClient)}, {$push: {dataOrders: resultOrder}}).then(function () {
log.debug('assignOrder', resultOrder, resultClient);
});
}).done();
}
};
执行所有“任务”但在w.all resultOrder和resultClient内部未定义..
答案 0 :(得分:0)
您的两个函数都返回undefined
。您正在从.then
处理程序正确返回值,但您根本没有从insertOrder
返回承诺:
var insertClient = function () {
// note the return
return dbClients.clients.insert(newClient).then(function (result) {
log.debug('mondialParser', 'addClient', result);
return result;
});
};
var insertOrder = function () {
//note the return
return dbOrders.orders.insert(order.Order).then(function(result) {
log.debug('mondialParser', 'addOrder', result);
return result;
});
};
Q.all([insertOrder(),insertClient()]).spread(function(order,client){
// access here
});
当Q.all
获得非承诺参数(在本例中为undefined
)时,它会将其转换为承诺,因此您在此处获得Q(undefined)
两次。
答案 1 :(得分:0)
要记住的核心原则是“承诺代表异步操作的结果”。这意味着它不需要执行,您只需要等待它完成(或拒绝)。调用方法后立即启动操作,就像使用同步代码一样。
但是,您可能希望了解mongod使用promise库而不是Q.这两个版本是可互操作的,因此这可能不会导致任何问题。如果您想将承诺变为Q承诺,您可以使用var QPromise = Q(nonQPromise);
。
您需要确保始终从onFulfilled
函数(作为.then
的第一个参数传递的函数)中继续返回promise。考虑到这一点,我会将原始代码重写为:
var dbOrders = mongo(db.serverConfig.name + "/" + db.databaseName, ['orders']);
var dbClients = mongo(db.serverConfig.name + "/" + db.databaseName, ['clients']);
var promise;
if (order.Order.Nif === "") {
var newClient = {
name: order.Order.Asegurado,
ni: order.Order.Nif,//Never used..
address: order.Order.Direccion,
city: order.Order.Poblacion,
province: order.Order.Provincia,
phone: order.Order.Telefonos,
cp: order.Order.CodigoPostal
};
promise = Q(dbClients.clients.insert(newClient).then(function (currentClient) {
log.debug('mondialParser', 'addClient', currentClient);
return dbOrders.orders.insert(order.Order).then(function (orderId) {
log.debug('mondialParser', 'addOrder', orderId);
return dbClients.clients.update({_id: new ObjectID(currentClient)}, {$push: {dataOrders: orderId}}).then(function () {
log.debug('assignOrder', orderId, currentClient);
});
});
}));
// optionally call promise.done to expose any errors:
promise.done(function () {
log.debug('operations complete');
}, function (err) {
log.debug('operations failed ' + (err.stack || err));
});
}
请注意,默认情况下,promises不会公开它们的错误,因为它们无法知道以后不会处理错误。您可以通过在promise链的末尾调用.done
来解决此问题,这表示您不希望处理任何其他错误。 Q和promise都支持此功能。
你的第二个例子(具有并行完成一些工作的优点)可以通过添加一些额外的return语句来修复:
var parseMondial = function (db, order, log) {
"use strict";
var dbOrders = mongo(db.serverConfig.name + "/" + db.databaseName, ['orders']);
var dbClients = mongo(db.serverConfig.name + "/" + db.databaseName, ['clients']);
if (order.Order.Nif === "") {
var newClient = {
name: order.Order.Asegurado,
ni: order.Order.Nif,//Never used..
address: order.Order.Direccion,
city: order.Order.Poblacion,
province: order.Order.Provincia,
phone: order.Order.Telefonos,
cp: order.Order.CodigoPostal
};
var insertClient = function () {
return dbClients.clients.insert(newClient).then(function (result) {
log.debug('mondialParser', 'addClient', result);
return result;
});
};
var insertOrder = function () {
return dbOrders.orders.insert(order.Order).then(function(result) {
log.debug('mondialParser', 'addOrder', result);
return result;
});
};
Q.all([insertOrder(), insertClient()]).spread(function (resultOrder, resultClient) {
return dbClients.clients.update({_id: new ObjectID(resultClient)}, {$push: {dataOrders: resultOrder}}).then(function () {
log.debug('assignOrder', resultOrder, resultClient);
});
}).done();
}
};
通过删除无关的功能,可以进一步简化:
var parseMondial = function (db, order, log) {
"use strict";
var dbOrders = mongo(db.serverConfig.name + "/" + db.databaseName, ['orders']);
var dbClients = mongo(db.serverConfig.name + "/" + db.databaseName, ['clients']);
if (order.Order.Nif === "") {
var newClient = {
name: order.Order.Asegurado,
ni: order.Order.Nif,//Never used..
address: order.Order.Direccion,
city: order.Order.Poblacion,
province: order.Order.Provincia,
phone: order.Order.Telefonos,
cp: order.Order.CodigoPostal
};
var resultOrderPromise = dbOrders.orders.insert(order.Order).then(function (result) {
log.debug('mondialParser', 'addOrder', result);
return result;
});
var resultClientPromise = dbClients.clients.insert(newClient).then(function (result) {
log.debug('mondialParser', 'addClient', result);
return result;
});
Q.all([resultOrderPromise, resultClientPromise]).spread(function (resultOrder, resultClient) {
return dbClients.clients.update({_id: new ObjectID(resultClient)}, {$push: {dataOrders: resultOrder}}).then(function () {
log.debug('assignOrder', resultOrder, resultClient);
});
}).done();
}
};
这仍然会并行执行两个插入,因为每个插入都在我们等待之前启动。调用异步函数会启动操作,并返回结果的承诺。
如果您想了解有关承诺如何运作的更完整的教程,请查看:https://www.promisejs.org/