【问题标题】:NodeJS promise (Q) .then its not calledNodeJS promise (Q) .then 它没有被调用
【发布时间】:2014-06-04 14:00:53
【问题描述】:

我试图用 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 内部是未定义的..

【问题讨论】:

  • Q.fcall(promise); 应该做什么? promise 是一个承诺,而不是一个函数。
  • 我认为这“执行”了承诺,对吗?这是我的第一个承诺使用。
  • 不,承诺并不代表您可以“开始”的“任务”。它确实代表任务的结果值,通常会在您启动任务时返回。在你的情况下,这就是你打电话给insert
  • mongod,你的意思是this library?
  • @Bergi 是的,我用其他方式编辑了我的问题代码..但失败了。

标签: javascript node.js mongodb promise


【解决方案1】:

要牢记的核心原则是“promise 代表异步操作的结果”。这意味着它不需要被执行,你只需要等待它被完成(或被拒绝)。只要调用方法,操作就会开始,就像使用同步代码一样。

但是,您可能希望知道mongod 使用promise 库,而不是Q。尽管两者是可互操作的,因此这可能不会导致任何问题。如果你想把一个promise变成一个Q promise,你可以使用var QPromise = Q(nonQPromise);

您需要确保始终从您的onFulfilled 函数内部返回承诺(作为第一个参数传递给.then 的承诺)。考虑到这一点,我会将您的原始代码重写为:

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

请注意,默认情况下,promise 不会暴露它们的错误,因为它们无法知道错误以后不会被处理。您可以通过在您的承诺链末尾调用.done 来解决此问题,这表明您不希望处理任何其他错误。 Q 和 promise 都支持这个功能。

您的第二个示例(具有并行执行某些工作的优点,只需添加一些额外的返回语句即可修复:

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

  }
};

这仍然并行执行两个插入,因为每个插入都是在我们等待任何内容之前开始的。调用异步函数启动操作,并为结果返回一个 Promise。

如果您想要更完整的关于 Promise 工作原理的教程,请查看:https://www.promisejs.org/

【讨论】:

    【解决方案2】:

    你的两个函数都返回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)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-18
      • 2016-05-13
      • 2017-01-09
      • 1970-01-01
      • 2016-06-02
      • 2020-08-10
      • 1970-01-01
      相关资源
      最近更新 更多