JavaScript Promise在解决问题时陷入困境

JavaScript Promise gets stuck at resolve

本文关键字:陷入困境 解决问题 Promise JavaScript      更新时间:2023-09-26

我有一个异步函数,我做了多次(2),但由于某种原因,promise在解析时被卡住了。它执行resolve(),但不执行任何操作。

以下是函数(基本上是从URL创建blob):

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 completed, resolving...");
        var burl = window.URL.createObjectURL(this.response);
        console.log("getBlobAt promise completed, resolving2...");
        resolve(burl);
        console.log("getBlobAt promise completed, resolving3...");
        //window.URL.revokeObjectURL(burl); //DO THIS WHEN LOADING NEW SONG
    };
    console.log("getBlobAt xhr.send() and callback");
    xhr.send();
    callback(xhr);
    //return xhr;
});
}

这是任务图:

            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 complete - 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 completed!");
                setPlayer(current_blob, current_blob_album);
                target.attr('class', 'glyphicon glyphicon-pause');
            });

它在第一次resolve()时被卡住。这是控制台输出:

Running a getBlobTask
New getBlobAt Call
getBlobAt Promise Created
getBlobAt xhr.send() and callback
getBlobTask callback
getBlobAt promise completed, resolving... 
getBlobAt promise completed, resolving2...
getBlobAt promise completed, resolving3...

您有一个针对0检查的g变量,但您没有在任何地方定义g

您没有看到这一点的原因是本机(或jQuery)承诺不会自动跟踪可能未处理的拒绝。

您可以通过在链的末尾附加一个.catch来检查是否有错误。

q.then(function (result) {
    ...
}).catch(function(e){
     console.log(e.message);
     console.log(e.stack);
});

这会让你看到这个问题。

或者,使用一个更强大的库,如Bluebird,它会在未处理的拒绝情况下提醒您。

Derp,看起来变量g突然出现。当我把它改成I时,它开始工作了。为什么我没有在控制台中得到一个错误呢?承诺是否在某种程度上抑制了错误?

您遇到了吞咽异常问题。

在接受的答案中提出的catch实际上和做then(null, fn)是一样的,它也是一个转换函数,会吞噬最终的异常(所以不是问题的真正解决方案)。

如果您只想处理值,最干净的方法是通过done(无误吞咽)

q.done(function (result) {
    // Process the result
});

然而,请注意,原生promise不提供done,并且由于没有提出错误吞噬的解决方案,因此最好不要使用原生promise(直到解决为止),而是使用一个流行的JS库(大多数都提供done)。

另请参阅:

  • https://stackoverflow.com/questions/22294425/promises-ecmascript-6-vs-3rd-party-libraries/22296765#22296765
  • promise.然后吞咽错误(这是演示幻灯片,使用光标四处移动)