node.js:从函数返回不按预期方式

我对javascript / node.js很陌生,而且遇到下面的代码有问题。 这是API调用的处理程序。 第二个代码段就像第一个代码段一样,除了有一个额外的数据库查找Merchant.findOne(…),因此'newTransaction.save()'函数嵌套更深一层。

两个代码段都正确地返回“输出”variables值。 但是,第二个代码段不能正确地将“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数据保存到MongoDB中的新代码。

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

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

在这里输入图像描述

检查1

ticket.quote

  • 这两个版本的callback是相同的
  • processorlocalCurrency是不同的

    1. exchangeRate传入callback是否正确?

检查2

newTransaction.save

  • newTransaction和.save的callback设置完全相同

    1. 检查(console.log())用于设置new Transaction({...})
    2. 检查callback接收的transaction对象
    3. 检查/debuggingTransaction.save()的代码。

我不认为这个问题是你发布的代码。 两个版本都达到了return reply(output); 在newTransaction.save的callback里面。 非常可能的问题是在Transaction类或Transaction.save()逻辑内。

我能想到的一种情况是交易失败:

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

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

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 

你也可以在这里find