Mehdi S. Mehdi S. - 3 months ago 43
Javascript Question

deferred/promise js mecanism on multiple firebase storage upload

i'm stuck with image upload to firebase database asynchronous mecanism in my project, here's my problematic:

i have a form where user put some info, the user also need to provide 4 photo to complete the upload process.

i use firebase database & firebase storage to handle this, here's the flow :


  • user fill form1 form2 & form3 with text based info

  • user select img1 img2 img3 img4 image from his computer

  • user clic submit all 4 image upload to firebase and give me 4 download url

  • i append all previously gathered information + 4 download url in a dictionary and ship it to firebase database



so the my deal is to create and ship the dictionary only when and if the 4 photo url are set, i heard about deferred/promise concept but i see a lot of Ajax request and no one with a similar issue, here is what i have for now

$("#submit-bag").click(function () {

var uploadDfdimg1 = function() {
var deferred = new $.Deferred();
var uploadTask = storageRef.child('images/' + $img1.name).put($img1);
uploadTask.on('state_changed', function(snapshot){
}, function(error) {
deferred.reject(error);
}, function() {
var downloadURL = uploadTask.snapshot.downloadURL;
console.log(downloadURL);
url1 = downloadURL;
deferred.resolve(downloadURL);

return deferred.promise();
});
}
var uploadDfdimg2 = function() {
var deferred = new $.Deferred();
var uploadTask = storageRef.child('images/' + $img2.name).put($img2);
uploadTask.on('state_changed', function(snapshot){
}, function(error) {
deferred.reject(error);
}, function() {
var downloadURL = uploadTask.snapshot.downloadURL;
console.log(downloadURL);
url2 = downloadURL;
deferred.resolve(downloadURL);

return deferred.promise();
});
}
$.when(uploadDfdimg1,uploadDfdimg2).then(
function(){console.log('double trouble success')},
function(){console.log(url1 + " deferred")},
function(){console.log(url2 + " deferred")});


var brand = $("#select1 option:selected").text()
var mail = document.getElementById('form1').value
var postal_code = document.getElementById('form2').value
var comment = document.getElementById('comment').value
//UPLOAD IMG

//uploadImg(img1,url1);
//uploadImg(img2,url2);
uploadImg(img3,url3);
uploadImg(img4,url4);

//console.log(url1);
//console.log(url2);
console.log(url3);
console.log(url4);
//PHOTO LINK VAR
var postData = {
marque: brand,
email: mail,
code_postal: postal_code,
commentaire: comment,
//PHOTO LINK
validation: 0
};
var newPostKey = firebase.database().ref().child('submission').push().key;
var updates = {};
updates['/submission/' + newPostKey] = postData;
firebase.database().ref().update(updates)


like you can see here, img3 & img4 upload themselves using the old non fonctionnal manner (downloadUrl come after the all dictionary PostData is send)

for img1 & img2 i tryed to use Deferred to see if i can get the 2 url at the same time when $.when.().then fired, normally after the success promise of the two uploadDfdimg function

the result is, i instantly get the "double trouble" log message with empty url variable, and normally after a second, the two url returned by firebase for img3 and img4

return log of the above code

how can i be able to asynchronously send 4 image to firebase, get the url, and at the end of this process, put the url in my dictionary to send it to my database ?

Answer

i tryed to refactor like this, but still get empty url1 & url2

var uploadDfdimg1 = function() {
    var deferred = new $.Deferred();
    var uploadTask = storageRef.child('images/' + $img1.name).put($img1);
    uploadTask.on('state_changed', function(snapshot){
    }, function(error) {
    deferred.reject(error);
    }, function() {
    var downloadURL = uploadTask.snapshot.downloadURL;
    console.log(downloadURL);
    url1 = downloadURL;
    deferred.resolve(downloadURL);
    });
    return deferred.promise();
}
var uploadDfdimg2 = function() {
    var deferred = new $.Deferred();
    var uploadTask = storageRef.child('images/' + $img2.name).put($img2);
    uploadTask.on('state_changed', function(snapshot){
    }, function(error) {
    deferred.reject(error);
    }, function() {
    var downloadURL = uploadTask.snapshot.downloadURL;
    console.log(downloadURL);
    url2 = downloadURL;
    deferred.resolve(downloadURL);
    });
    return deferred.promise();
}
$.when( uploadDfdimg1, uploadDfdimg2 ).done( function() {
    console.log(url1 + " deferred");
    console.log(url2 + " deferred");
});
Comments