I have an async function that I do multiple times (2), but for some reason the promise get stuck at resolve. It executes resolve(), but doesn't do anything.
Here's the function (basically creates a blob from an URL):
function getBlobAt(url, callback) {
console.log("New getBlobAt Call");
return new Promise(function(resolve) {
console.log("getBlobAt Promise Created");
window.URL = window.URL || window.webkitURL;
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function () {
console.log("getBlobAt promise pleted, resolving...");
var burl = window.URL.createObjectURL(this.response);
console.log("getBlobAt promise pleted, resolving2...");
resolve(burl);
console.log("getBlobAt promise pleted, resolving3...");
//window.URL.revokeObjectURL(burl); //DO THIS WHEN LOADING NEW SONG
};
console.log("getBlobAt xhr.send() and callback");
xhr.send();
callback(xhr);
//return xhr;
});
}
And here's the task map:
var taskstrings = [endmp3, albumart];
var getBlobTasks = taskstrings.map(function (xurl, i) {
return function () {
console.log("Running a getBlobTask");
return getBlobAt(xurl, function (xhr) {
console.log("getBlobTask callback");
if (g == 0) { //First one is always the mp3 link
current_xhr = xhr;
} else {
current_xhr_album = xhr;
}
}).then(function (res) {
console.log("getBlobTask plete - returning!");
if (g == 0) { //First one is always the mp3 link
current_blob = res;
} else {
current_blob_album = res;
}
return res;
});
};
});
var q = getBlobTasks[0](); // start the first one
for (var i = 1; i < getBlobTasks.length; i++) q = q.then(getBlobTasks[i]);
q.then(function (result) {
//Both globs have been returned
console.log("All getBlobTasks pleted!");
setPlayer(current_blob, current_blob_album);
target.attr('class', 'glyphicon glyphicon-pause');
});
It gets stuck at the first resolve(). This is the console output:
Running a getBlobTask New getBlobAt Call getBlobAt Promise Created getBlobAt xhr.send() and callback getBlobTask callback getBlobAt promise pleted, resolving... getBlobAt promise pleted, resolving2... getBlobAt promise pleted, resolving3...
I have an async function that I do multiple times (2), but for some reason the promise get stuck at resolve. It executes resolve(), but doesn't do anything.
Here's the function (basically creates a blob from an URL):
function getBlobAt(url, callback) {
console.log("New getBlobAt Call");
return new Promise(function(resolve) {
console.log("getBlobAt Promise Created");
window.URL = window.URL || window.webkitURL;
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function () {
console.log("getBlobAt promise pleted, resolving...");
var burl = window.URL.createObjectURL(this.response);
console.log("getBlobAt promise pleted, resolving2...");
resolve(burl);
console.log("getBlobAt promise pleted, resolving3...");
//window.URL.revokeObjectURL(burl); //DO THIS WHEN LOADING NEW SONG
};
console.log("getBlobAt xhr.send() and callback");
xhr.send();
callback(xhr);
//return xhr;
});
}
And here's the task map:
var taskstrings = [endmp3, albumart];
var getBlobTasks = taskstrings.map(function (xurl, i) {
return function () {
console.log("Running a getBlobTask");
return getBlobAt(xurl, function (xhr) {
console.log("getBlobTask callback");
if (g == 0) { //First one is always the mp3 link
current_xhr = xhr;
} else {
current_xhr_album = xhr;
}
}).then(function (res) {
console.log("getBlobTask plete - returning!");
if (g == 0) { //First one is always the mp3 link
current_blob = res;
} else {
current_blob_album = res;
}
return res;
});
};
});
var q = getBlobTasks[0](); // start the first one
for (var i = 1; i < getBlobTasks.length; i++) q = q.then(getBlobTasks[i]);
q.then(function (result) {
//Both globs have been returned
console.log("All getBlobTasks pleted!");
setPlayer(current_blob, current_blob_album);
target.attr('class', 'glyphicon glyphicon-pause');
});
It gets stuck at the first resolve(). This is the console output:
Share Improve this question edited Dec 25, 2014 at 11:20 Benjamin Gruenbaum 277k89 gold badges520 silver badges517 bronze badges asked Apr 15, 2014 at 15:46 FabisFabis 2,0723 gold badges23 silver badges42 bronze badges 0Running a getBlobTask New getBlobAt Call getBlobAt Promise Created getBlobAt xhr.send() and callback getBlobTask callback getBlobAt promise pleted, resolving... getBlobAt promise pleted, resolving2... getBlobAt promise pleted, resolving3...
3 Answers
Reset to default 7You have a g
variable you check against 0
but you did not define g
anywhere.
The reason you did not see this is that native (or jQuery) promises do not automatically track possibly unhandled rejections.
You can check for errors by appending a .catch
to the end of the chain and see if anything went wrong.
q.then(function (result) {
...
}).catch(function(e){
console.log(e.message);
console.log(e.stack);
});
Which would have shown you the issue.
Alternatively, use a stronger library like Bluebird that will alert you in the case of unhandled rejections.
Derp, looks like the variable g appeared out of nowhere. When I changed it to i, it started working. Why didn't I get an error in the console, though? Do promises suppress errors in some way?
You've run into swallowed exception issue.
Proposed catch
in accepted answer is actually same as doing then(null, fn)
, it's also transformation function that will swallow eventual exceptions (so not real solution for your problem).
If you just want to process the value, cleanest way is via done
(with no error swallowing implied)
q.done(function (result) {
// Process the result
});
However mind that native promises do not provide done
, and as there's no solution for error swallowing proposed, it's best to not use native promises (until that's solved) and use one of the popular JS libraries instead (most of them provide done
).
See also:
- https://stackoverflow./questions/22294425/promises-ecmascript-6-vs-3rd-party-libraries/22296765#22296765
- promise.then error swallowing (it's presentation slides, use cursors to move around).