Javascript HTML:如何在执行函数之前获得计算结果

Javascript HTML:如何在执行函数之前获得计算结果,javascript,html,google-cloud-firestore,Javascript,Html,Google Cloud Firestore,我有一个脚本,我正试图执行。我需要脚本,在按下提交按钮时: 从Google firestore获取值 在计算中使用这些值 使用此计算的结果写回firestore数据库 我将console.log(“eff[1,2,3]”+计算结果)放在控制台日志中,以帮助跟踪执行顺序。它首先显示eff3,然后显示eff1,然后显示eff2,这意味着提交给firestore的值为零(与计算前一样)。计算会计算正确答案,但不会将答案提交给数据库 如何更改代码以使其按正确的顺序执行 // Triggered when

我有一个脚本,我正试图执行。我需要脚本,在按下提交按钮时:

  • 从Google firestore获取值
  • 在计算中使用这些值
  • 使用此计算的结果写回firestore数据库
  • 我将
    console.log(“eff[1,2,3]”+计算结果)
    放在控制台日志中,以帮助跟踪执行顺序。它首先显示
    eff3
    ,然后显示
    eff1
    ,然后显示
    eff2
    ,这意味着提交给firestore的值为零(与计算前一样)。计算会计算正确答案,但不会将答案提交给数据库

    如何更改代码以使其按正确的顺序执行

    // Triggered when the send new message form is submitted.
    function onMessageFormSubmit(e) {
      e.preventDefault();
      //Calculate efficiency
      var preodo = 0
      var efficiency = 0
      firebase.firestore().collection('Vehicle').doc(reg.value).collection('Refuels').orderBy('Date', 'desc').limit(1)
        .onSnapshot(function(snapshot) {
          snapshot.docChanges().forEach(function(change) {
            preodo = change.doc.data().Odometer
            efficiency = (odo.value - preodo) / amount.value
            efficiency = efficiency.toFixed(4);
            console.log("eff1:" + efficiency)
          });
          console.log("eff2:" + efficiency)
        });
      //Save refuel transaction with all details form the form as well as the calculated efficiency        
      console.log("eff3:" + efficiency)
      saveMessage(reg.value, odo.value, date.value, amount.value, price.value, rebate.value, efficiency).then(function() {
        window.alert('Refuel submitted!')
        // Clear message text field and re-enable the SEND button.
        resetMaterialTextfield();
        toggleButton();
      });
    }
    

    通过使用@Professor Abronsius的建议,我把我的代码放在了一个
    承诺中

    //提交发送新邮件表单时触发。
    函数onMessageFormSubmit(e){
    e、 预防默认值();
    让我承诺=新承诺(函数(myResolve,myReject){
    //计算效率
    var preodo=0
    var效率=0
    firebase.firestore().collection('Vehicle').doc(reg.value.).collection('refells').orderBy('Date','desc').limit(1)
    .onSnapshot(功能(快照){
    snapshot.docChanges().forEach(函数(更改){
    preodo=change.doc.data().里程表
    效率=(odo.value-preodo)/amount.value
    效率=效率。toFixed(4);
    console.log(“eff1:+效率)
    });
    console.log(“eff2:+效率)
    myResolve(效率);//成功时
    myReject(“无法计算效率”);//出错时
    });
    });
    //“消费代码”(必须等待承诺兑现)
    我的承诺,那么(
    职能(效率){
    //保存加油事务,包括表单中的所有详细信息以及计算的效率
    console.log(“eff3:+效率)
    saveMessage(reg.value、odo.value、date.value、amount.value、price.value、retriep.value、efficiency){
    window.alert('加油已提交!')
    //清除消息文本字段并重新启用发送按钮。
    resetMaterialTextfield();
    切换按钮();
    });
    },
    函数(错误){
    window.alert(错误)
    }
    );
    
    }
    通过使用@Professor Abronsius的建议,我把我的代码放在了一个
    承诺中

    //提交发送新邮件表单时触发。
    函数onMessageFormSubmit(e){
    e、 预防默认值();
    让我承诺=新承诺(函数(myResolve,myReject){
    //计算效率
    var preodo=0
    var效率=0
    firebase.firestore().collection('Vehicle').doc(reg.value.).collection('refells').orderBy('Date','desc').limit(1)
    .onSnapshot(功能(快照){
    snapshot.docChanges().forEach(函数(更改){
    preodo=change.doc.data().里程表
    效率=(odo.value-preodo)/amount.value
    效率=效率。toFixed(4);
    console.log(“eff1:+效率)
    });
    console.log(“eff2:+效率)
    myResolve(效率);//成功时
    myReject(“无法计算效率”);//出错时
    });
    });
    //“消费代码”(必须等待承诺兑现)
    我的承诺,那么(
    职能(效率){
    //保存加油事务,包括表单中的所有详细信息以及计算的效率
    console.log(“eff3:+效率)
    saveMessage(reg.value、odo.value、date.value、amount.value、price.value、retriep.value、efficiency){
    window.alert('加油已提交!')
    //清除消息文本字段并重新启用发送按钮。
    resetMaterialTextfield();
    切换按钮();
    });
    },
    函数(错误){
    window.alert(错误)
    }
    );
    
    }
    Firestore操作是异步的,因此您需要承诺处理它们。完全按照使用
    saveMessage()
    所做的操作,但返回一个值

    另外,请使用
    .get()
    而不是
    .onSnapshot()
    ,因为后者将继续侦听对引用文档所做的更改,您不需要这些更改,因为您在单击按钮时执行此操作

    function get_efficiency(regValue) {
        efficiency = -1
        // return a Promise which will return the efficiency after all computations are done
        return firebase.firestore().collection('Vehicle')
            .doc(reg.value)
            .collection('Refuels')
            .orderBy('Date', 'desc')
            .limit(1)
            .get()
            .then(function (querySnapshots) { // this will execute after all documents are fetched from the db
                querySnapshots.forEach(function(doc) {
                    preodo = doc.data().Odometer
                    efficiency = (odo.value - preodo) / amount.value
                    efficiency = efficiency.toFixed(4);
                    console.log("eff1:" + efficiency)
                });
                console.log("eff2:" + efficiency)
                return efficiency
            })
    }
    
    
    // Triggered when the send new message form is submitted.
    function onMessageFormSubmit(e) {
        e.preventDefault();
        //Calculate efficiency
        var preodo = 0
        var efficiency = 0
    
        get_efficiency(reg.value)
            .then(function (efficiency) { // this will execute after you computed the efficiency
            // efficiency param is the one returned from the PROMISE from get_efficiency()
        
            //Save refuel transaction with all details form the form as well as the calculated efficiency        
            console.log("eff3:" + efficiency)
            saveMessage(reg.value, odo.value, date.value, amount.value, price.value, rebate.value, efficiency).then(function() {
                window.alert('Refuel submitted!')
                // Clear message text field and re-enable the SEND button.
                resetMaterialTextfield();
                toggleButton();
            });
        })
    }
    

    Firestore操作是异步的,因此您需要承诺处理它们。完全按照使用
    saveMessage()
    所做的操作,但返回一个值

    另外,请使用
    .get()
    而不是
    .onSnapshot()
    ,因为后者将继续侦听对引用文档所做的更改,您不需要这些更改,因为您在单击按钮时执行此操作

    function get_efficiency(regValue) {
        efficiency = -1
        // return a Promise which will return the efficiency after all computations are done
        return firebase.firestore().collection('Vehicle')
            .doc(reg.value)
            .collection('Refuels')
            .orderBy('Date', 'desc')
            .limit(1)
            .get()
            .then(function (querySnapshots) { // this will execute after all documents are fetched from the db
                querySnapshots.forEach(function(doc) {
                    preodo = doc.data().Odometer
                    efficiency = (odo.value - preodo) / amount.value
                    efficiency = efficiency.toFixed(4);
                    console.log("eff1:" + efficiency)
                });
                console.log("eff2:" + efficiency)
                return efficiency
            })
    }
    
    
    // Triggered when the send new message form is submitted.
    function onMessageFormSubmit(e) {
        e.preventDefault();
        //Calculate efficiency
        var preodo = 0
        var efficiency = 0
    
        get_efficiency(reg.value)
            .then(function (efficiency) { // this will execute after you computed the efficiency
            // efficiency param is the one returned from the PROMISE from get_efficiency()
        
            //Save refuel transaction with all details form the form as well as the calculated efficiency        
            console.log("eff3:" + efficiency)
            saveMessage(reg.value, odo.value, date.value, amount.value, price.value, rebate.value, efficiency).then(function() {
                window.alert('Refuel submitted!')
                // Clear message text field and re-enable the SEND button.
                resetMaterialTextfield();
                toggleButton();
            });
        })
    }
    

    我的猜测是,从未使用过Google Firestore的
    onsnapshot
    方法是异步的,但是您的代码以同步方式运行
    savemessage
    方法。您是否可以将
    Promise
    添加到
    onSnapshot
    方法中,并使用解析的值继续程序流程?您是否可以将
    saveMessage
    code向上移动到“eff2”行之后?@carljdp,如果我这样做,它会多次提交保存,就像它在loop@JillianWittstock,我明白了。在进一步调试时,我还没有更多的建议。我猜,从未使用过Google Firestore的情况下,
    onsnapshot
    方法是异步的,但是您的代码以同步方式运行
    savemessage
    方法。您是否可以将
    Promise
    添加到
    onSnapshot
    方法中,并使用解析的值继续程序流程?您是否可以将
    saveMessage
    code向上移动到“eff2”行之后?@carljdp,如果我这样做,它会多次提交保存,就像它在loop@JillianWittstock,我明白了。在进一步的调试中,我还没有更多的建议。它似乎对数据库中的每个条目都重复循环,所以seco