Синхронность for в js

209
22 августа 2017, 14:58

Всем привет. Есть задача - реализовать синхронный вызов файла через childProcess.execFile(). Вариант childProcess.execFileSync() не подходит, поскольку не имеет коллбека, а мне это очень важно. Каким образом в данном коде можно сделать цикл for (i = 0; i < sites.lenght; i++) синхронным? Проблема в том, что при запуске всего скрипта, виснет комп из-за 3500 асинхронных процессов через execFile()

   var  express             = require("express"),
        request             = require('request'),
        bodyParser          = require("body-parser"),
        fs                  = require("fs"),
        colors              = require('colors/safe'),
        phantomjs           = require('phantomjs'),
        childProcess        = require('child_process'),     
        path                = require('path');
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
var binPath = phantomjs.path;
var childArgs;
var sites = [];
fs.readFile('sites.txt', { encoding : 'utf8' },
    (err, data) => {
        if (err) throw err;
        data.split('\n').forEach(line => {
            sites.push(line.slice(0,-1));
    });     
    for (i = 0; i < sites.lenght; i++) {

        var site = 'http://' + sites[i] + "/";

        var childArgs = [
            path.join(__dirname, 'prod.js'),
            site
        ];      
        childProcess.execFile(binPath, childArgs, function(err, stdout, stderr) {   
            console.log(stdout);
            const dom = new JSDOM(stdout);
            var links = dom.window.document.links;
            for (var i = 0; i < links.length; i++) {
                if(links[i].href.indexOf('vk.com') + 1) {
                    var str = "\r\n"+site+':'+links[i].href;
                    fs.appendFile('success.txt', str, function (err) {
                        if (err) {
                            console.log(err);
                        } else {                    
                            console.log(str);                                                       
                        }
                    });
                }
            }
        });
    }   
});
Answer 1

Дак а в чем проблема использовать собственно callback? Вам нужно не использовать цикл for, а сделать следующее Занести childProcess.execFile в функцию, которая будет принимать помимо значений, передаваемых в childProcess.execFile еще и currentPostition, totalPositions а в коллбэке проверять - если текущая позиция (currentPosition) равна количеству позиций (totalPositions) - то просто вернуть true, иначе увеличить текущую позицию на единицу и выполнить эту функцию уже для следующего файла. Т.е. получится рекурсия - пока не исполнится последний файл. Надеюсь, алгоритм понятен.

Ну а если вам коллбэк нужен только после того как исполнятся все файлы - то заносите это в условие "если текущая позиция равна количеству позиций"

Answer 2

В принципе, можно было бы воспользоваться следующим решением: Как последовательно вызвать асинхронную функцию с коллбеками?.

Но вообще-то в твоём случае правильнее использовать синхронный вариант функции и вызывать желаемый callback самостоятельно в try-catch.

READ ALSO
Замена определенного тэга при помощи javascript

Замена определенного тэга при помощи javascript

Здравствуйте, на обработку поступает текст примера:

200
Сложить значение нескольких полей в MySql

Сложить значение нескольких полей в MySql

Всем приветЕсть 8 полей, (price1, price2, price3,

370
Nordea bank file transfering [требует правки]

Nordea bank file transfering [требует правки]

Необходимо реализовать класс для отправки запроса к банку и получение в ответ файл (Incoming reference payments (XML)Почитал документы которые являются...

228