Reputation: 105449
I have a custom method that executes async functions which DO NOT return promises. My custom method does return a promise. What is the correct way to implement the functionality - using timeout like in example 1 or checking for equality in the callback function like in example 2?
EXAMPLE 1:
getAllFiles: function () {
var def = $.Deferred();
var files = [];
fileEntries.forEach(function(fileEntry){
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onload = function (e) {
files.push({
name: fileEntry.fullPath,
content: e.target.result
});
};
reader.readAsArrayBuffer(file);
});
});
//this resolves the deffered
var interval = setInterval(function(){
if (files.length === fileEntries.length) {
def.resolve(files);
clearInterval(interval);
}
}, 1000);
return def.promise();
}
EXAMPLE 2
getAllFiles: function () {
var def = $.Deferred();
var files = [];
fileEntries.forEach(function(fileEntry){
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onload = function (e) {
files.push({
name: fileEntry.fullPath,
content: e.target.result
});
//this resolves the deffered
if (files.length === fileEntries.length) {
def.resolve(files);
clearInterval(interval);
}
};
reader.readAsArrayBuffer(file);
});
});
return def.promise();
}
This question is not about how to pass an array of promises to the when
function since neither file
method nor onload
return promises.
Upvotes: 0
Views: 123
Reputation: 664297
Simply make a promise for each async function (onload
handler) then!
getAllFiles: function () {
var deferreds = fileEntries.map(function(fileEntry){
var def = $.Deferred();
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onload = function (e) {
def.resolve({
name: fileEntry.fullPath,
content: e.target.result
});
};
reader.onerror = def.reject; // don't forget error handling!
reader.readAsArrayBuffer(file);
}, def.reject); // here as well
return def;
});
return $.when.apply($, deferreds).then(function() {
var files = $.map(arguments, function(args) { return args[0]; });
return files;
});
}
(the map
ping over the arguments in the then
is necessary because jQuery's $.when
result is so ugly)
To answer your actual question:
What is the correct way to implement the functionality - using timeout like in example 1 or checking for equality in the callback function like in example 2?
Do it from the callback. Polling results with setInterval
is despised (it's slower, won't catch errors and even leak in the error case).
Upvotes: 1