Обещания Node.js Q.all не работает

У меня есть эта функция readLines для разбора строки за строкой, которая вызывается из:

var fs = require('fs');
var Q = require('q');

Q.all(readLines(fs.createReadStream("/tmp/test.txt"), console.log)).then(function () {
    console.log('Done');
};

function readLines(input, func) {
    var remaining = '';

    input.on('data', function (data) {
        remaining += data;
        var index = remaining.indexOf('\n');
        while (index > -1) {
            var line = remaining.substring(0, index);
            remaining = remaining.substring(index + 1);
            func(line);
            index = remaining.indexOf('\n');
        }
    });

    input.on('end', function () {
        if (remaining.length > 0) {
            func(remaining);
        }
    });
};

Может ли кто-нибудь помочь, почему я никогда не получал "Готово"? Какой-нибудь учебник, чтобы понять, как работают промисы?


person user3377078    schedule 04.03.2014    source источник
comment
Обещания не работают с потоками. Пожалуйста, перечитайте, что Q.all ожидает в качестве своего аргумента - ваша readLines функция не return ничего делает.   -  person Bergi    schedule 04.03.2014


Ответы (1)


Это будет работать лучше для вас. Пожалуйста, прочтите комментарии в коде — на самом деле там всего несколько дополнительных строк, включая добавление обработки ошибок.

var fs = require('fs');
var Q = require('q');

// you don't need Q.all unless you are looking for it to resolve multiple promises.
// Since readlines returns a promise (a thenable), you can just then() it.
readLines(fs.createReadStream("./vow.js"), console.log).then(function (x) {
    console.log('Done',  x);
});

function readLines(input, func) {
    // you need to create your own deferred in this case - use Q.defer()
    var deferred = Q.defer();
    var remaining = '';

    input.on('data', function(data) {
        remaining += data;
        var index = remaining.indexOf('\n');
        while (index > -1) {
            var line = remaining.substring(0, index);
            remaining = remaining.substring(index + 1);
            func(line); 
            index = remaining.indexOf('\n');
        }
    });

    input.on('end', function() {
        if (remaining.length > 0) {
            func(remaining);
            console.log('done');
        }
        // since you're done, you would resolve the promise, passing back the 
        // thing that would be passed to the next part of the chain, e.g. .then()
        deferred.resolve("Wouldn't you want to return something to 'then' with?");
    });

    input.on('error', function() {
        console.log('bother');
        // if you have an error, you reject - passing an error that could be
        // be caught by .catch() or .fail()
        deferred.reject(new Error('Regrettable news - an error occured.'));
    });
    // you return the promise from the deferred - not the deferred itself
    return deferred.promise;
};
person barry-johnson    schedule 04.03.2014
comment
Что там делает Q.all? - person Bergi; 04.03.2014
comment
На самом деле не так много, кроме как тратить время на выполнение. Хорошая мысль - в данном случае избыточная, поскольку есть только одно обещание уладить. Редактирую сейчас. По иронии судьбы, именно ваш комментарий к OP «перечитайте, что Q, all() ожидает в качестве аргумента», побудил меня просто посмотреть, с чем он вызывается, а не на его фактическую полезность здесь. - person barry-johnson; 04.03.2014
comment
Вы очень кстати. Рад, что помог. Что касается вышеупомянутого обмена между Берги и мной - Q.all() обычно предназначен для получения массива (обещаний). Q.all() и в противном случае потерпит неудачу - как только одно из его обещаний-членов будет отклонено. Вы можете использовать Q.allSettled(), если хотите, чтобы он пытался выполнить все обещания, даже если одно из них не выполняется. - person barry-johnson; 04.03.2014