Node.js: Возврат из функции, не действующей как ожидалось

Я очень новичок в javascript/ node.js, и у меня возникают проблемы со следующим кодом. Это обработчик API для вызова. Второй сегмент кода похож на 1-й, за исключением того, что есть дополнительный поиск в базе данных Merchant.findOne(...), и поэтому функция newTransaction.save() вложен на один уровень глубже.

Оба сегмента кода правильно возвращают значение "output". Однако второй сегмент кода НЕ также правильно сохраняет "newTransaction" в базе данных Mongo.

Я уверен, что проблема связана с тем, как/когда код возвращается из newTransaction.save(функция (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));
            }
        });
    }

Ответы

Ответ 1

Я сделал разницу в вашей 2 версии:

введите описание изображения здесь

Проверить 1

ticket.quote

  • Обратный вызов идентичен для обеих версий
  • processor, localCurrency отличаются

    • Правильно ли exchangeRate в обратный вызов?

Проверить 2

newTransaction.save

  • newTransaction и обратный вызов для .save устанавливаются идентичными

    • Проверьте (console.log()) значения, используемые при настройке new Transaction({...})
    • Проверить transaction объект, полученный обратным вызовом
    • Проверить/отладить код Transaction.save().

Я не думаю, что проблема связана с кодом, который вы опубликовали. Обе версии достигли return reply(output); внутри newTransaction.save обратного вызова. Очень вероятно, что проблема заключается в классе Transaction или Transaction.save().

Один сценарий, о котором я могу думать, - это когда транзакция завершилась неудачно:

  • Объект транзакции доступен (даже для неудавшейся транзакции)
  • Класс транзакции /Transaction.save() не записывается в db, поскольку транзакция завершилась неудачно
  • 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

Вы также можете найти то же самое здесь