【问题标题】:JavaScript Promise gets stuck at resolveJavaScript Promise 卡在了 resolve
【发布时间】:2014-04-15 15:46:55
【问题描述】:

我有一个异步函数,我多次执行 (2),但由于某种原因,promise 卡在了 resolve。它执行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...

【问题讨论】:

    标签: javascript jquery promise jquery-deferred resolve


    【解决方案1】:

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

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

    您可以通过将.catch 附加到链的末尾来检查错误,看看是否有任何问题。

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

    这会向您显示问题。

    或者,使用像 Bluebird 这样更强大的库,它会在出现未处理的拒绝时提醒您。

    【讨论】:

    【解决方案2】:

    Derp,看起来变量 g 不知从何而来。当我将其更改为 i 时,它开始工作。但是,为什么我没有在控制台中收到错误消息?承诺是否以某种方式抑制错误?

    【讨论】:

    • 哇,我猜我的答案是错误的,但显然它是正确的,我取消了它。
    • @Fabis 如果您使用thencatch,他们会这样做,请参阅promise.then error swallowing(使用光标移动)
    【解决方案3】:

    您遇到了吞咽异常问题。

    在接受的答案中提出的catch 实际上与then(null, fn) 相同,它也是一种转换功能,可以吞下最终的异常(因此不是真正解决您的问题的方法)。

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

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

    但是请注意,原生 Promise 不提供 done,并且由于没有建议的错误吞咽解决方案,因此最好不要使用原生 Promise(在解决之前)并改用流行的 JS 库之一(其中大部分提供done)。

    另见:

    【讨论】:

      猜你喜欢
      • 2018-01-08
      • 1970-01-01
      • 2016-08-17
      • 1970-01-01
      • 2019-12-14
      • 2021-12-13
      • 2019-01-20
      • 2021-11-05
      • 2017-10-20
      相关资源
      最近更新 更多