JavaScript。用户函数中的 promise 。为什么不起作用?

标签 javascript firebase firebase-realtime-database promise google-cloud-functions

任务:在主函数中,调用两个函数,第一个函数包含异步方法。

在ReadValueBalances函数中,once()方法返回Promise。然后我使用 then() 并返回结果。 之后,应启动第二个函数 UpdateValueMapBalances。

但是,为什么首先执行 UpdateValueMapBalances,而不是 ReadValueBalances?

    'use strict';

// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const FBfunctions = require('firebase-functions');

// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();




exports.UpdateBalancesUser = FBfunctions.database.ref('/{userID}/Movements').onWrite((MoveDataChange, context) => {
    const UserID = String(context.params.userID);   
    const BalanceRef = admin.database().ref('/'+ UserID +'/Balances') ;

    var Date_first, Date_last;
    var Value_first = 0; 
    var Value_last = 0;

    var TypeofChange = 0;
    MoveDataChange.after.forEach((childMove) => {
        if (!childMove.exists()) {
            console.log('MoveDataChange.after: нет!');
            //return false;  //выходим из функции
        }
        Date_last = childMove.child('dateInMilisec').val();
        Value_last = childMove.child("value").val()*childMove.child("kind").val();  
        console.log('Date_last: ', Date_last, '. Value_last: ', Value_last);
        TypeofChange = TypeofChange +1;
        //return true;
    });

    MoveDataChange.before.forEach((childMove) => {
        if (!childMove.exists()) {
            console.log('MoveDataChange.before: нет!');
            //return false;  //выходим из функции
        }
        Date_first = childMove.child('dateInMilisec').val();
        Value_first = -childMove.child("value").val()*childMove.child("kind").val();    //с обратным знаком, т.к. его не стало
        console.log('Date_first: ', Date_first, '. Value_first: ', Value_first);
        TypeofChange = TypeofChange - 1;
        //return true;
    });

    console.log('TypeofChange: ', TypeofChange);

    if (TypeofChange < 0) {             // удалили движение
        Date_last = Date_first; 
        Value_last = 0;             
    }
    if (TypeofChange > 0) {             // новое движение
        Date_first = Date_last; 
        Value_first = Value_last;
        Value_last = 0;         
    }

    if (Date_first > Date_last) {      //меняем местами
        let Date_tmp = Date_first;
        Date_first = Date_last;
        Date_last = Date_tmp;
        let Value_tmp = Value_first;
        Value_first = Value_last;
        Value_last = Value_tmp;
    }


    let BalanceMap = new Map;
    let BalanceMapUpdate = new Map;
    return ReadValueBalances(Date_first, BalanceRef)
        .then(UpdateValueMapBalances(BalanceMap, Date_first, Date_last, Value_first, Value_last))
        .then((BalanceMapUpdate)=>{
            return BalanceRef.update(BalanceMapUpdate, ()=>{
                console.log('Записали изменения ', BalanceMapUpdate);
            })
        }); 
});

function ReadValueBalances(Date_1, BalanceRef){  
    var BalancesMap = new Map;
    return BalanceRef.orderByKey().startAt(String(Date_1)).once('value')      // считываем значения БД после даты записи движения
        .then((DataSnapShot)=>{
            console.log('ReadValueBalances Получили выгрузку от ', Date_1);
            if (!DataSnapShot.exists()) {                                       // если после даты ничего, то считываем последнее значение до даты движения
                console.log('ReadValueBalances Получаем последнюю запись');                     
                return BalanceRef.orderByKey().endAt(String(Date_1)).limitToLast(1).once('value');                  
            } 
            else {
                console.log('ReadValueBalances Выгрузка есть');
                return DataSnapShot;
            }
        })
        .then((DataSnapShot)=>{         
            DataSnapShot.forEach((snapshot)=>{                  // цикл по элементам выгрузки. записываем в Map
                BalancesMap.set(snapshot.key, snapshot.val());
                console.log('snap key: ', snapshot.key, ' value:', snapshot.val());             
            });
            console.log('ReadValueBalances Закончили цикл');
            return BalancesMap;
        }); 
}


function UpdateValueMapBalances(BalanceMap_input, Date1, Date2, Delta1, Delta2){
    var BalanceMap_output = new Map;
    const Date_1 = new Date(Date1);
    const Date_2 = new Date(Date2); 
    console.log('UpdateValueMapBalances Date_1: ', Date_1, ' Date_2: ', Date_2);
    if (BalanceMap_input.size === 0) {
        console.log('UpdateValueMapBalances вх.коллекция пустая');
        var Date_item = new Date(Date_1);   
        console.log('UpdateValueMapBalances Date_item: ', Date_item);
        Date_item.setDate(1);
        Date_item.setMonth(Date_item.getMonth()+1);
        BalanceMap_output.set(Date_item.getMilliseconds(), Delta1);
        console.log('UpdateValueMapBalances BalanceMap_output: ', BalanceMap_output);
        return BalanceMap_output;
    }

    BalanceMap_input.forEach((ValueItem, KeyItem, MapItem)=>{
        console.log('ValueItem: ', ValueItem, ' KeyItem: ', KeyItem);   
        if (KeyItem <= Date1) {                 // возможно только в случае, если в выгрузке только 1 значение (до даты движения)
            console.log('UpdateValueMapBalances Дополняем коллекцию сверху');
            var bool_stop = false;
            var Date_item = new Date(KeyItem);                  
            Date_item.setDate(1); // на всякий случай
            console.log('Date_item ', Date_item);
            while (!bool_stop) {
                Date_item.setMonth(Date_item.getMonth()+1);
                if ((Date_item-Date_1) <= 0) {
                    BalanceMap_output.set(Date_item.getMilliseconds, ValueItem);    
                } else {
                    BalanceMap_output.set(Date_item.getMilliseconds, ValueItem + Delta1);  // в случае с удалением delta 1= -Value
                    bool_stop = true;
                }
            }
            console.log('UpdateValueMapBalances Дополнили коллекцию сверху');   
            return BalanceMap_output;  //TODO: выйти из цикла               
        } else {
            console.log('UpdateValueMapBalances Изменяем коллекцию снизу');             
            if (KeyItem <= Date2) {          // т.е. коллекция имеет значения после Date_first до Date_last. Срабатывает только если даты отличаются
                BalanceMap_output.set(KeyItem, ValueItem + Delta1);     
            } else {                                    // т.е. коллекция имеет значения после Date_last
                BalanceMap_output.set(KeyItem, ValueItem + Delta1 + Delta2);    // в случае с новым движением/удалением Delta2=0, а Delta1= -Value
            }
            console.log('UpdateValueMapBalances Изменили коллекцию снизу');
        }       
    })
    return BalanceMap_output;

日志:

2:23:26.362 PM
outlined_flag   
UpdateBalancesUser
Function execution took 1699 ms, finished with status: 'ok'
2:23:26.356 PM
info    
UpdateBalancesUser
Записали изменения Map { '1522540800000' => 200000 }
2:23:26.353 PM
info    
UpdateBalancesUser
ReadValueBalances Закончили цикл
2:23:26.353 PM
info    
UpdateBalancesUser
snap key: 1522540800000 value: 200000
2:23:26.353 PM
info    
UpdateBalancesUser
ReadValueBalances Выгрузка есть
2:23:26.352 PM
info    
UpdateBalancesUser
ReadValueBalances Получили выгрузку от 1519862400000
2:23:25.861 PM
info    
UpdateBalancesUser
UpdateValueMapBalances BalanceMap_output: Map { [Function: getMilliseconds] => -400000 }
2:23:25.860 PM
info    
UpdateBalancesUser
UpdateValueMapBalances Date_item: 2018-03-01T00:00:00.000Z
2:23:25.860 PM
info    
UpdateBalancesUser
UpdateValueMapBalances вх.коллекция пустая
2:23:25.860 PM
info    
UpdateBalancesUser
UpdateValueMapBalances Date_1: 2018-03-01T00:00:00.000Z Date_2: 2018-03-01T00:00:00.000Z
2:23:25.849 PM
info    
UpdateBalancesUser
TypeofChange: 0
2:23:25.849 PM
info    
UpdateBalancesUser
Date_first: 1519862400000 . Value_first: -400000

最佳答案

问题出在这一行

 .then(UpdateValueMapBalances(BalanceMap, Date_first, Date_last, Value_first, Value_last))

分解一下,then 需要一个函数作为参数 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

但发生的情况是您直接调用 UpdateValueMapBalances ,并且其返回值被用作 then

的参数

这里用稍微不同的写法来说明:

const successFunction = UpdateValueMapBalances(BalanceMap, Date_first, Date_last, Value_first, Value_last);

...


.then(successFunction)

假设您通过参数正确传递了所有正确的数据,将该函数调用包装在另一个函数中有望解决您的问题。这里有太多的事情我无法讲述。

.then(() => UpdateValueMapBalances(BalanceMap, Date_first, Date_last, Value_first, Value_last)

关于JavaScript。用户函数中的 promise 。为什么不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50795845/

相关文章:

ios - Swift 乱序执行 firebase 调用

javascript - 如何使用子字符串查询 firebase 键

javascript - onclick 功能它仅在第二次单击后才起作用

android - Xamarin.android 默认 FirebaseApp 未在此过程中初始化

javascript - 主干事件点击表格行

java - 如何使用 JsonAutoDetect 实现旧 Firebase 中可用的技巧?

node.js - 名为 '[DEFAULT]' 的 Firebase 应用程序已经存在,并且 google firebase 引用在服务器上不起作用

android - 在android firebase中获取父节点

javascript - `this._super(controller,model)` 在 Ember 路由器中意味着什么?

javascript - jQuery查找不存在的对象