javascript promise in loop or how to call function

2019-04-13 11:17发布

问题:

I work with slimerjs. So I have an array with urls and function (foo) that makes something with one url. This function return Promise.

It's ok if I do somth like this:

 foo(urls).then(foo, orError).then(foo, orError).....

But I want to call foo() in loop, so I try this:

for ( var i = 0; i < urls.length; i++ ) { foo(urls).then(foo, error); }

But it doesnt work.

Maybe I dont need promises here, i dunno.

How can I call async function in loop, but wait until function finish?

Here's my "foo" function:

function visitPage(urls) {
    return new Promise(function(success, error) {
        var url = urls.shift();
        if (!url) error();
        logger.log("Opening " + url);
        page
            .open(url)
            .then(function(status) {
                if (status !== "success") error();
                return page.evaluate(function() {
                    return document.body.innerHTML;
                });
            }).then(function(body) {
                var founded = looker.lookForAlpari(body);
                logger.log(founded);
                page.close();
                success(urls);
            });
    });
}

and here's my loop

for ( var i = 0; i < urls.length; i++ ) {
    visitPage(urls)
      .then(visitPage, showError);
}

回答1:

Similar to my answer here the technique is to chain the actions themselves, either by an actual for loop or by a .reduce. Since you asked for a for loop let's stick to that:

var queue = Promise.resolve(); // start waiting
urls.forEach(function(url){
     queue = queue.then(function(result){
        // put result somewhere
        return visitPage(url);
    });
});
queue.then(function(){
     // all done here
});

You can change visitPage to only take a url rather than mutate urls which should be nicer anyway.