Firebase管理员顺序调用,返回值和承诺

时间:2018-05-13 10:24:40

标签: node.js firebase google-cloud-functions firebase-admin

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 :(得分:0)

在我的拙见中,有一些事情需要在您的代码中进行微调,如下所示。我在代码中发表了评论。

但请注意,由于我们不知道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);
});