Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
268 views
in Technique[技术] by (71.8m points)

javascript - promise resolve before inner promise resolved

I have a promise and I want it to resolve only when inner promise has resolved. Right now it resolves before the "resolve" function has been reached in the "loadend" callback.

What am I missing? I am confused about the way you are supposed to use resolve and about how you can use a promise within another promise.

I couldn't find anything that helped on the web.

In the following example I basically load a bunch of files, for each file I get a blob and I want to pass this blob in a file reader.

Once all files have been passed to the file reader, I want to move to the next function in the promise chain.

Right now it goes to the next function in the chain without waiting for resolve to be called.

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);
    });
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When you don't return anything from then callbacks, it assumes synchronous operation and goes to resolve the result promise with the result (undefined) immediately.

You need to return a promise from every asynchronous function, including then callbacks that you want to get chained.

Specifically, your code should become

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';
            });
        })
    });
});

or even better, 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';
    });
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...