1

I am using AngularJS and AngularFire.

I am using two $firebaseArrays containing objects that are essentially alternate versions of each other. They contain different data, but are added to and deleted from the arrays concurrently because they must always align with each other. For this reason, I need to save them both using the same Firebase-generated unique id's.

The saved arrays are copied in my component so they can be altered enabling the option to either save the changes back to the original arrays, or discard them.

//The currently saved versions of the arrays.
var db = firebase.database().ref();

var mainArrayRef = db.child('mainArray');
var alternateArrayRef = db.child('alternateArray');

vm.originalMainArray = $firebaseArray(mainArrayRef);
vm.originalAlternateArray = $firebaseArray(alternateArrayRef);

//Copy the original arrays in order to make changes that can then be saved.
vm.activeMainArray = angular.copy(vm.originalMainArray);
vm.activeAlternateArray = angular.copy(vm.originalAlternateArray);

vm.activeMainArray.push( { value: x } );
vm.activeAlternateArray.push( { value: y } );

When adding new items to the arrays, I need to loop through the activeMainArray, save the data to Firebase and attach the unique key that is generated by Firebase to each item in the array so that when the activeAlternateArray is processed, the corresponding object can be saved using the same firebase generated unique id as it's main counterpart.

function saveObjectsToFirebase(originalArray, activeArray, preprocessedArray){

    //preprocessedArray is available during the processing of the alternateArray

    var promises = [];

    for(var i=0; i < activeArray.length; i++){

        var newObject = angular.copy(activeArray[i]);

        //If this is the main array, use standard methods to create unique id.
        if(!preprocessedArray){
            promises.push(originalArray.$add(newObject)
            .then(function(firebaseObject){

                //The newly created firebase id is attached to the object.
                activeArray[i].id = firebaseObject.key
                console.log(newObject.id)
            })
        }

        //If this is the alternateArray (and the main array has been preprocessed and sent to this function)...
        if(preprocessedArray){

            //Get the firebase id from the corresponding object in the main array.
            var id = preprocessedArray[i].id;

            promises.push(originalArray.$ref().child(id).set(newObject))

        }

    return promises;
}

var mainArrayPromises = saveObjectsToFirebase(vm.originalMainArray, vm.activeMainArray);

$q.all(mainArrayPromises).then(function(){

    var alternateArrayPromises = saveObjectsToFirebase(vm.originalAlternateArray, vm.activeAlternateArray, vm.activeMainArray);


    $q.all(alternateArrayPromises).then(function(){
        //The rest of the function
    });
});

All I need to do is to ensure that by the time $q.all(mainArrayPromises) runs, the .then() function that attaches the firebase key to the objects in the main array have already completed so the key is available when the alternate array is processed. I assume it is going to involve $q.when() or $q.defer(), but I'm not sure how to implement that within this structure of a promise array being generated within loops.

Strangely enough, the console.log output will log the id BEFORE the second array is processed at which point the id will not actually be available and will be undefined. I have no idea how this is the case.

I hope this makes sense and my thanks in advance for your time.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
J Dawg
  • 525
  • 1
  • 5
  • 14
  • Change `for(var i = 0;` to `for(let i = 0;`. Also `var newObject` to `let newObject`. – georgeawg Apr 24 '18 at 14:25
  • Thanks but I am not using any ES6 – J Dawg Apr 24 '18 at 22:54
  • Then use an [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression) to create the block level scope needed to preserve the variables. – georgeawg Apr 25 '18 at 03:53
  • @georgeawg, thanks for your help. I didn't realise that this was a problem due to the scope of variables within the loop changing before the .then() ran. I thought it was something to do with the .then() functions for the promises running after the $q.all(), which is why I couldn't find an answer that made sense. Apologies for the duplicate question. – J Dawg Apr 26 '18 at 01:54

0 Answers0