Search code examples
javascriptnode.jsunderscore.jslodashbluebird

How to iterate an array synchronously using lodash, underscore or bluebird


I have an array that contains filenames at each index. I want to download those files one at a time (synchronously). I know about 'Async' module. But I want to know whether any functions in Lodash or Underscore or Bluebird library supports this functionality.


Solution

  • You can use bluebird's Promise.mapSeries:

    var files = [
        'file1',
        'file2'
    ];
    
    var result = Promise.mapSeries(files, function(file) {
        return downloadFile(file); // << the return must be a promise
    });
    

    Depending on what you use to download file, you may have to build a promise or not.

    Update 1

    An exemple of a downloadFile() function using only nodejs:

    var http = require('http');
    var path = require('path');
    var fs = require('fs');
    
    function downloadFile(file) {
        console.time('downloaded in');
        var name = path.basename(file);
    
        return new Promise(function (resolve, reject) {
            http.get(file, function (res) {
                res.on('data', function (chunk) {
                    fs.appendFileSync(name, chunk);
                });
    
                res.on('end', function () {
                    console.timeEnd('downloaded in');
                    resolve(name);
                });
            });
        });
    }
    

    Update 2

    As Gorgi Kosev suggested, building a chain of promises using a loop works too:

    var p = Promise.resolve();
    files.forEach(function(file) {
        p = p.then(downloadFile.bind(null, file));
    });
    
    p.then(_ => console.log('done'));
    

    A chain of promise will get you only the result of the last promise in the chain while mapSeries() gives you an array with the result of each promise.