最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery - JavaScript Promise gets stuck at resolve - Stack Overflow

programmeradmin6浏览0评论

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:

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...
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 0
Add a ment  | 

3 Answers 3

Reset to default 7

You 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).
发布评论

评论列表(0)

  1. 暂无评论