【问题标题】:node.js: Return from function not acting as expectednode.js:从函数返回未按预期运行
【发布时间】:2016-08-16 13:16:25
【问题描述】:

我对 javascript/node.js 非常陌生,但在使用以下代码时遇到了问题。这是 API 调用的处理程序。第 2 段代码和第 1 段一样,只是多了一个数据库查找 Merchant.findOne(...),因此 'newTransaction.save()' 函数嵌套更深一层。

两个代码段都正确返回了“输出”变量值。但是,第二个代码段也没有正确地将“newTransaction”保存到 Mongo 数据库中。

我很确定问题与代码从 newTransaction.save(function (err, transaction){..} 返回的方式/时间有关,但我似乎无法理顺。

我一直在寻找整个互联网试图理解和解决这个问题,但没有成功。任何帮助表示赞赏...

这是按预期工作的较旧、更简单的代码:

 handler : function(request, reply) {

        var output = {
            "success": true,
            "operations": [],
            "epoch": Date.now()
        };


        Terminal.findById(request.payload.deviceNumber, function (err, terminal) {
            if (err) {
                return reply(Boom.internal('Error looking up terminal.', err));
            }
            if (terminal) {

                ticket.quote("bitstamp", "USD", 1, function (err, exchangeRate) {
                    if (err) {
                        console.error(err);
                        return reply(Boom.internal('Error obtaining ticket quote.', err));
                    }

                  var newTransaction = new Transaction({
                        terminal: request.payload.deviceNumber,
                        merchant: terminal.merchant,
                        ccExchangeRate: exchangeRate.buy,
                        fiatAmtDue: request.payload.transactionValue,
                        ccAmtDue: ccAmtDueTruncated
                    });

                    newTransaction.save(function (err, transaction){
                        if (err) {
                            return reply(Boom.internal('Error creating new transaction.', err));
                        }

                        output.operations.push(
                            {
                                "control": "KeyPairGenControl",
                                "rand": cc.pseudoRandomBytes(32).toString('hex'),
                                "follow": {
                                    "url": "/pos/v1/AddressAndEncKey",
                                    "post": {
                                        "transactionId": transaction.transactionId
                                    }
                                }
                            }
                        );

                        return reply(output);

                    });

                });
            } else {
                return reply(Boom.internal('Error looking up terminal.', err));
            }
        });
    }

这是不将 newTransaction 数据保存到 Mongo DB 中的新代码。

handler : function(request, reply) {

        var output = {
            "success": true,
            "operations": [],
            "epoch": Date.now()
        };


        Terminal.findById(request.payload.deviceNumber, function (err, terminal) {
            if (err) {
                return reply(Boom.internal('Error looking up terminal.', err));
            }
            if (terminal) {

                Merchant.findOne({merchantId: terminal.merchant}, function(err, merchant) {
                    if (err) {
                        console.log('Cannot find merchant');
                        return reply(output);
                    }
                    var processor = merchant.backendPaymentProcessor.name;
                    var localCurrency = merchant.localFiatCurrency;
    //###################
                    ticket.quote(processor, localCurrency, 1, function (err, exchangeRate) {
                        if (err) {
                            console.error(err);
                            return reply(Boom.internal('Error obtaining ticket quote.', err));
                        }

                        var newTransaction = new Transaction({
                            terminal: request.payload.deviceNumber,
                            merchant: terminal.merchant,
                            ccExchangeRate: exchangeRate.buy,
                            fiatAmtDue: request.payload.transactionValue,
                            ccAmtDue: ccAmtDueTruncated
                        });

                        newTransaction.save(function (err, transaction){
                            if (err) {
                                return reply(Boom.internal('Error creating new transaction.', err));
                            }

                            output.operations.push(
                                {
                                    "control": "KeyPairGenControl",
                                    "rand": cc.pseudoRandomBytes(32).toString('hex'),
                                    "follow": {
                                        "url": "/pos/v1/AddressAndEncKey",
                                        "post": {
                                            "transactionId": transaction.transactionId
                                        }
                                    }
                                }
                            );

                            return reply(output);

                        });

                    //return reply(output);

                    });
    //###################
                });
            } else {
                return reply(Boom.internal('Error looking up terminal.', err));
            }
        });
    }

【问题讨论】:

    标签: javascript node.js mongodb


    【解决方案1】:

    我做了你的 2 版本的差异:

    检查 1

    ticket.quote

    • 两个版本的回调相同
    • processorlocalCurrency 不同

      1. exchangeRate 传入回调是否正确?

    检查 2

    newTransaction.save

    • newTransaction 和 .save 的回调设置相同

      1. 检查(console.log())设置new Transaction({...})时使用的值
      2. 检查回调收到的transaction对象
      3. 检查/调试 Transaction.save() 的代码。

    我认为问题不在于您发布的代码。两个版本都在 newTransaction.save 的回调中达到了 return reply(output);。很可能问题出在 Transaction 类或 Transaction.save() 逻辑内部。

    我能想到的一个场景是事务失败时:

    1. 事务对象可用(即使对于失败的事务)
    2. 事务类/Transaction.save() 未写入数据库,因为事务失败
    3. Transaction.save() 将transaction 对象传递给回调,但不设置err,即使它应该设置。

    【讨论】:

      【解决方案2】:

      Mongoose 具有在模式下指定集合名称的功能,或者在声明模型时作为第三个参数。否则,它将使用您映射到模型的名称给出的复数版本。

      Mongoose 官方文档有如下声明:

      默认情况下,Mongoose 通过将模型名称传递给 utils.toCollectionName 方法来生成集合名称。此方法将名称复数。如果您的收藏需要不同的名称,请设置此选项。

      架构映射:

      new Schema({ <key>: <value>}, 
             { collection : '<collection name>' });   // collection name
      

      模型映射:

      mongoose.model('<Model name>', 
                 new Schema({ <key>: <value>}), 
                 '<collection name>');     // collection name
      

      You may also find same here

      【讨论】:

        猜你喜欢
        • 2012-01-21
        • 1970-01-01
        • 2020-06-02
        • 1970-01-01
        • 2011-10-31
        • 2023-03-13
        • 1970-01-01
        • 2022-07-10
        • 1970-01-01
        相关资源
        最近更新 更多