NodeJS承诺(Q)。然后它没有被调用

时间:2014-06-04 14:00:53

标签: javascript node.js mongodb promise

我试图通过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内部未定义..

2 个答案:

答案 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/

相关问题