0

I've implemented the following code example in a script which loops over an array of results and makes an http request for each one.

function sequence(array, callback) {
    return array.reduce(function chain(promise, item) {
        return promise.then(function () {
            return callback(item);
        });
    }, Promise.resolve());
};

var products = ['sku-1', 'sku-2', 'sku-3'];

sequence(products, function (sku) {
    return getInfo(sku).then(function (info) {
        console.log(info)
    });
}).catch(function (reason) {
    console.log(reason);
});

function getInfo(sku) {
    console.log('Requested info for ' + sku);
    //assume this function makes an http request and returns a  promise
}

The script does not exit once all items in the array have been processed. How would I adapt it so that this happens?

My implementation makes an API call and returns a promise:

....

}).then(function(results){
sequence(results, function(result){

    checkSpam(result).then(function(akismet){
        if(akismet) {
            //console.log('spam returned from checkspam');
            write_spam_to_file(result);
        } else {

            //console.log('no spam returned from checkspam');
        }
    })
});

}).catch(function (e) {
    console.log('Error occurred:');
    console.log(e);
});


function sequence(array, callback) {
    return array.reduce(function chain(promise, item) {
        return promise.then(function () {
            return callback(item);
        });
    }, Promise.resolve());
}

function checkSpam(entry) {

    var akismetPromise = new Promise(function resolver(resolve, reject) {
        akismet.checkSpam({
            user_agent: 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1',
            referrer: 'http://google.com',
            user_ip: entry.ip,
            comment_author: entry.poster,
            comment_content: entry.message,
            comment_type: 'forum-post'


        }, function (err, spam) {
            if (err) reject(err);
            resolve(spam);
        });

    });
    return akismetPromise;

}
codecowboy
  • 9,835
  • 18
  • 79
  • 134
  • What exactly do you mean by "does not exit"? You mean node doesn't stop running? That's hardly caused by the promises, rather by `akismet` or whatever you are using. – Bergi Mar 23 '16 at 19:26
  • @Bergi I am new to promises so wasn't sure if I had done something incorrectly. I've added a bit more code in case that sheds any light. Thanks for taking a look. – codecowboy Mar 23 '16 at 19:42
  • When looping through arrays you can return false from within the loop method to stop the iteration. – Silkster Mar 23 '16 at 19:52

1 Answers1

3

In contrast to your first snippet, your actual code lacks a bunch of return keywords:

    …
}).then(function(results) {
    return sequence(results, function(result) {
//  ^^^^^^
        return checkSpam(result).then(function(akismet) {
//      ^^^^^^
            if (akismet) {
                return write_spam_to_file(result);
//              ^^^^^^ // assuming the write is asynchronous and returns a promise?
            }
        });
    });
}) …

If you don't always return a promise from asynchronous functions (including then callbacks), the promise chain doesn't know what to wait for, and executes the next callback without waiting for any results.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    we need a canonical on forgotten returns these questions are returning a ton of times. "Promise not waiting for action" or something like that, the problem is that is sounds a little too generic... – Benjamin Gruenbaum Mar 23 '16 at 21:33
  • @BenjaminGruenbaum: Yeah, but the next canonical I'm going to write is about asynchronous loops :-) (unless we already have a good one?) – Bergi Mar 23 '16 at 21:53