【问题标题】:promise resolve before inner promise resolved在内部承诺解决之前承诺解决
【发布时间】:2015-06-24 07:33:25
【问题描述】:

我有一个承诺,我希望它仅在内部承诺解决后才解决。现在它在“loadend”回调中的“resolve”函数到达之前解析。

我错过了什么?我对您应该使用 resolve 的方式以及如何在另一个 Promise 中使用 Promise 感到困惑。

我在网上找不到任何有用的东西。

在下面的示例中,我基本上加载了一堆文件,对于每个文件,我都会得到一个 blob,并且我想将这个 blob 传递到文件阅读器中。

一旦所有文件都传递给文件阅读器,我想移动到承诺链中的下一个函数。

现在它会转到链中的下一个函数,而无需等待调用 resolve。

var list = [];
var urls = this.files;

urls.forEach(function(url, i) {
    list.push(
        fetch(url).then(function(response) {
            response.blob().then(function(buffer) {

                var promise = new Promise(
                    function(resolve) {

                        var myReader = new FileReader();
                        myReader.addEventListener('loadend', function(e) {
                            // some time consuming operations
                            ...
                            window.console.log('yo');
                            resolve('yo');
                        });

                        //start the reading process.
                        myReader.readAsArrayBuffer(buffer);
                    });

                promise.then(function() {
                    window.console.log('smooth');
                    return 'smooth';
                });

            });
        })
    );
});

...

// run the promise...
Promise
    .all(list)
    .then(function(message){
        window.console.log('so what...?');
    })
    .catch(function(error) {
        window.console.log(error);
    });

【问题讨论】:

    标签: javascript promise ecmascript-6 resolve es6-promise


    【解决方案1】:

    当您没有 return 来自 then 回调的任何内容时,它假定同步操作并立即使用结果 (undefined) 解决结果承诺。

    您需要return 来自每个异步函数的承诺,包括您想要链接的then 回调。

    具体来说,你的代码应该变成

    var list = this.files.map(function(url, i) {
    //                   ^^^^ easier than [] + forEach + push
        return fetch(url).then(function(response) {
            return response.blob().then(function(buffer) {
                return new Promise(function(resolve) {
                    var myReader = new FileReader();
                    myReader.addEventListener('loadend', function(e) {
                        …
                        resolve('yo');
                    });
                    myReader.readAsArrayBuffer(buffer);
                }).then(function() {
                    window.console.log('smooth');
                    return 'smooth';
                });
            })
        });
    });
    

    甚至更好,flattened:

    var list = this.files.map(function(url, i) {
        return fetch(url).then(function(response) {
            return response.blob();
        }).then(function(buffer) {
            return new Promise(function(resolve) {
                var myReader = new FileReader();
                myReader.addEventListener('loadend', function(e) {
                    …
                    resolve('yo');
                });
                myReader.readAsArrayBuffer(buffer);
            });
        }).then(function() {
            window.console.log('smooth');
            return 'smooth';
        });
    });
    

    【讨论】:

    • 我有两个函数都返回了一个包含嵌套承诺的承诺,(由于模块设计),在嵌套承诺的末尾,我调用了包含承诺的解析,但觉得这是错误的。但是由于您的示例,我已经能够放弃包含的承诺,而只是返回了嵌套的承诺链。这使我的代码更易于阅读。我只是想为此竖起大拇指。
    猜你喜欢
    • 2021-08-11
    • 1970-01-01
    • 1970-01-01
    • 2018-04-02
    • 2016-12-06
    • 1970-01-01
    • 2015-06-23
    • 2019-04-13
    相关资源
    最近更新 更多