Reputation: 11153
Can someone please explain to me why my q.all is not working?
I have 5 promises that download images to blob files. I have another 5 promises which upload these blobs to the servers I use. I use a backend-as-a-service Quickblox so the callback on a successful upload provides the Amazon AWS url link. I need to take all these links and upload them to my servers so that I know which user is associated with which images.
The 5 downloads and uploads seem to work, but the upload to the url is not working. Before each resolve happens in the uploads function, the callback sets $scope.amazon_urls
= to the callback url provided. Therefore when Q.all.runs, I expect all $scope.amazon_urls
to exist. This however is not the case. What is going on?
Order of functions is: 1)
Here is the function to upload urls. I've commented the sections that I'm thinking is causing issues.
function uploadURLs(scope,principal){
QB.data.list(className,{user_id:principal.user_id},function(err,res){
if (err){
console.log(err);
return err;
} else {
console.log(res)
var data = {
_id: res.items[0]._id,
image1: scope.amazon_urls[0], // Accessing these values should all be set after q.all
image2: scope.amazon_urls[1], // A null value indicates that
image3: scope.amazon_urls[2], //the callback function has not set it yet
image4: scope.amazon_urls[3], // however this function should occur after q.all
image5: scope.amazon_urls[4] // so shouldn't this all be set already?
}
QB.data.update(className,data,function(e,r){
if (e){
console.log(e);
return e;
} else {
console.log(r);
return r;
}
});
}
});
}
Here is the button that executes the download / upload promises and pushes them into an array $scope.promises
$scope.selectPictureForProfile = function(t){
var deferred = $q.defer();
var qbdeferred = $q.defer();
var promise = xhrPromise(deferred,t.photo,$scope,$scope.currently_selected).then(function(blob){
QBCreateAndUploadPromise(qbdeferred,$scope,$scope.currently_selected,blob);
});
$scope.promises.push(promise);
}
Here is the button that runs q.all. Once everything is resolved,
$scope.save_photos = function(){
$q.all($scope.promises).then(function(response){
uploadURLs($scope,principal); // this seems to execute before last promise
});
}
Here is the function to download images...
function xhrPromise(deferred,url,scope,i){
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var myBlob = this.response;
scope.image_blobs[i] = myBlob;
deferred.resolve(myBlob);
} else {
deferred.reject("");
}
};
xhr.send();
return deferred.promise;
}
Here is the function to upload images...
function QBCreateAndUploadPromise(deferred,scope,i,blob){
QB.content.createAndUpload({'file':blob,'name':"profilepics.jpg", 'type':"image/jpeg", 'public': true },function(e,r){
if(e){
deferred.reject("error");
} else {
scope.amazon_urls[i]= "http://qbprod.s3.amazonaws.com/" + r.uid;
deferred.resolve("http://qbprod.s3.amazonaws.com/"+ r.uid);
}
});
return deferred.promise;
}
Upvotes: 1
Views: 1620
Reputation: 11153
After much difficulty it turns out that q.all
was firing right after my first promises were fired.
However since I chained that first set of promises I was expecting q.all
to fire after the second set of promises.
In order to get them to fire after the first set I had to create an array of promises for the first set then use
.then(function(){$q.all(second_set_of_promises).then(third_final_set_of_promises)});
In this way, the third set of promises only fires after the second set is complete and the second set only fires when the first set is complete.
Upvotes: 1