如何在嵌套的Promise中停止函数执行

时间:2018-07-23 16:46:09

标签: javascript node.js firebase firebase-realtime-database triggers

关于诺言,我是一个初学者,我正试图了解如何使用它们。

我有一个Firebase触发器,正在执行一些验证。如果验证失败,我想“退出”触发器,这意味着验证后我不想执行任何代码(假设验证失败)。但是确实如此。即使我确定验证失败(“由于不活动,您已超时。请返回床单预订地图并重新开始”已发送至我正在开发的android应用),之后的代码仍会保留执行。我知道这是因为我已经在其中放置了控制台日志。

我已经在我的代码中添加了注释,以用于我正在谈论的验证以及不希望执行的代码。

exports.createCharge = functions.database.ref('/customers/{userId}/charges/{id}')
  .onCreate((snap, context) => {
    console.log("Entered createharge function");
    const val = snap.val();
    return admin.database().ref(`/customers/${context.params.userId}/customer_id`)
      .once('value').then((snapshot) => {
        return snapshot.val();
      }).then((customer) => {

        // Do stuff

        if (val.type === 'beds') {
          // Check if user email is the same as bed email
          for (var i = 0; i < val.beds.length; i++) {
            var bedEmailRef = db.ref(`beds/${val.hid}/${val.beds[i]}/email`);
            bedEmailRef.on("value", function(bedEmailSnap) {
              var bedEmail = bedEmailSnap.val();
              if (val.email !== bedEmail) { // VALIDATION
                snap.ref.child('error').set("You have been timed out due to inactivity. Please go back to the bed booking map and start again"); 
                return null; // Here, I want to exit the whole function. 
              }
            });
          }

          // If val.email !== bedEmail, I NEVER want to reach here!
          return admin.database().ref(`/hotels/${val.hid}/bedPrice`)
            .once('value').then((tempBedPrice) => {
                // do stuff
              console.log("got here");
              return stripe.charges.create(charge, {idempotency_key: idempotencyKey});
            }).then((response) => {
              // Do more stuff
              return snap.ref.set(response);
            }).catch((error) => {
              snap.ref.child('error').set(userFacingMessage(error));
              return reportError(error, {user: context.params.userId});
            })

        } else throw Error('No type');
      });
  });

为什么我会得到这种行为?验证执行后如何停止代码?

2 个答案:

答案 0 :(得分:0)

问题是您要在检查“床”类型后添加“侦听器”。一种解决方案是fetch data once

 // This is a snippet from Firebase documentation
 return firebase.database().ref('/users/' + 
   userId).once('value').then(function(snapshot) {
      var username = (snapshot.val() && snapshot.val().username) || 
     'Anonymous';
     // ...
 });

或重构代码,以便您的验证可以设置为满足某些条件时可以返回的回调。

另外,这里有一个link for Cloud functions best practices,可以帮助您编写更好的云功能。

答案 1 :(得分:0)

如果您要退出/不想再在监听器上发生任何事件,请按如下所示重构代码:

       bedEmailRef.on("value", function(bedEmailSnap) {
          var bedEmail = bedEmailSnap.val();
          if (val.email !== bedEmail) { // VALIDATION
            snap.ref.child('error').set("You have been timed out due to inactivity. Please go back to the bed booking map and start again"); 
            bedEmailRef.off('value'); // This will stop listening for further events
            return null; // This is useless because returning inside a listener has no effect
          }
        });