Последовательный вызов администратора Firebase, возвращаемые значения и обещания - PullRequest
0 голосов
/ 13 мая 2018

0) У меня есть триггер HTTP:

exports.checkout = functions.https.onRequest((req, res) => {

1) Обновлять транзакции пополнения счета, когда пользователь покупает пакет topUp:

admin.database().ref('topupTransaction').push(topUpObject)

2) Получить объект пользователя (с балансом счета)

admin.database().ref('/users/' + userID).once("value",snap=> {

3) Установить новый объект пользователя (с новым балансом аккаунта)

admin.database().ref('/users/' + req.query.userUid).set(topUpObject);

Я не уверен, как запустить все эти (1,2,3) последовательно и вернуть значение клиенту (0). Удар не должен включать обещание. Есть Promise.all, но как его использовать в этом случае.

Нажав «Избегать вложенных обещаний». когда я пытаюсь сделать это следующим образом:

exports.checkout = functions.https.onRequest ((req, res) => { var nonceFromTheClient = req.body.payment_method_nonce;

  var topUpObject = {
    amount : parseInt(req.query.topUpPackage),
    date : admin.database.ServerValue.TIMESTAMP, // 1525451616097
    user : req.query.userUid
  };

  admin.database().ref('topupTransaction').push(topUpObject)
  .then((topUpResult) => {
    return admin.database().ref('/users/' + userID).once("value");
  }).then((oldUserData)=>{
    return admin.database().ref('/users/' + req.query.userUid).set(topUpObject).then((newUserData)=>{
      return res.send(newUserData.val());
    })
      ;
  }).catch((error) => {
    // Update databse failed (top up transaction)
    console.log('Error sending message:', error);
    return res.status(500).send(error);
  });

Обновление

с использованием Promise.all, но частично работает с ошибками:

// Create 2 functions
function asyncFunction1(topUpObject){
    // Push top up object to database
    admin.database().ref('topupTransaction').push(topUpObject)
      .then((response) => {
        // Update databse successful (top up transaction)
        console.log('Top Up transaction created successfully!', topUpObject);
        // return res.redirect(303, response.ref);
        return topUpObject;
      }).catch((error) => {
        // Update databse failed (top up transaction)
        console.log('Error sending message:', error);
        return error;
      });
}

function asyncFunction2(userID,topUpObject){
    // Get the user account balance
    console.log('Current User ID: ', userID);
    var ref = admin.database().ref('users').child(userID);
    admin.database().ref('/users/' + userID).once("value",snap=> {
      // do some stuff once
      console.log('Current User Data',snap.val());
      console.log('Current User balance',snap.val().accountBalance);
      var userContents = snap.val();
      var currentBalance = userContents.accountBalance;
      var updatedBalance = currentBalance + topUpObject.amount;
      console.log('Updated Balance',updatedBalance);
      userContents.accountBalance = updatedBalance;
      /*Current User Data { 
        accountBalance: 0,
        accountCurrency: 'MYR',
        createdOn: '2018-05-02T20:42:49Z',
        phoneNumber: '+123445555555'
      }
      */
      admin.database().ref('/users/' + userID).set(userContents).then(snapshot => {
        console.log('Updated top up value! for user', topUpObject);
        return res.send(topUpObject.amount);  
      }).catch((error) => {
        // Update databse failed (top up transaction)
        console.log('Error sending message:', error);
        return error;
      });

    });
}

// app.post("/checkout", function (req, res) {
exports.checkout = functions.https.onRequest((req, res) => {
  var nonceFromTheClient = req.body.payment_method_nonce;
  // Use payment method nonce here

  // Create Transaction
  gateway.transaction.sale({ 
    amount: req.query.topUpPackage,
    paymentMethodNonce: nonceFromTheClient,
    options: {
      submitForSettlement: true
    }
  },(err, result) => { //TODO: What should we pass back here???
    if (err) {
    // If top up error (from braintree)
      console.log(err.stack);
    }else{
    // If top up is successful
      console.log('Result:',result);
      console.log('Top Up Package is: ', req.query.topUpPackage);
      var topUpObject = {
        amount : parseInt(req.query.topUpPackage),
        date : admin.database.ServerValue.TIMESTAMP, // 1525451616097
        user : req.query.userUid
      };
      return Promise.all([asyncFunction1(topUpObject), asyncFunction2(req.query.userUid,topUpObject)]); //TODO: how to pass back res() to client???
    }
    // Return the error as response
    return res.send(err);
  });
});

exports.client_token = functions.https.onRequest((req, res) => {

    // a token needs to be generated on each request
    // so we nest this inside the request handler

    // Need to write a function to return a client token,
    // and return it back by using the res.send command
    console.log('Log customerId',req.query.text);

    gateway.clientToken.generate({
      // customerId: req.query.text
    }, (err, response) => {
      // error handling for connection issues
      if (err) {
        console.log(err.stack);
      }else{
        clientToken = response.clientToken;
        console.log('Log Client token:',clientToken);
        return res.send(clientToken);
      }
      return res.send(err);
    });
    // return null;
});

1 Ответ

0 голосов
/ 13 мая 2018

По моему скромному мнению, есть несколько вещей, которые нужно отрегулировать в вашем коде следующим образом.Я прокомментировал код.

Однако учтите, что, поскольку мы не знаем, откуда взялась (и что это), topUpObject, точнее сказать немного.Если вы поделитесь более подробной информацией (полный код функции облака и структура базы данных), я могу быть более точным.

admin.database().ref('topupTransaction').push(topUpObject)
    .then(topUpResult => {
        return admin.database().ref('/users/' + userID).once("value");
    })
    .then(oldUserData => {
         return admin.database().ref('/users/' + req.query.userUid).set(topUpObject);  
         //Set returns a non-null firebase.Promise containing void
    })
    .then(() => {  //so I don't think you can get the newUserData here
        //return res.send(newUserData.val());  <- and therefore you cannot do that here
        //But if I understand well you want to send back to the user the topUpObject, so do as follows:
        return res.status(200).send(topUpObject);  //<- note the addition of status(200) here
    })
    .catch((error) => {
        // Update databse failed (top up transaction)
        console.log('Error sending message:', error);
        return res.status(500).send(error);
});
...