2016-04-15 3 views
0

У меня есть файл, в котором я пишу вещи:nodejs: Как ждать несколько асинхронных задач, чтобы закончить

var stream = fs.createWriteStream("my_file.txt"); 
stream.once('open', function(fd) { 
    names.forEach(function(name){ 
    doSomething(name); 
    }); 
    stream.end(); 
}); 

Это работает нормально, и я могу записать в файл. Проблема заключается в том, что функция doSomething() имеет некоторые части, которые являются асинхронными. Примером может служить функция dnsLookup. Где-то в моем DoSomething() У меня есть:

dns.lookup(domain, (err, addresses, family) => { 
    if(err){ 
    stream.write("Error:", err); 
    }else{ 
    stream.write(addresses); 
    } 
}); 

Теперь моя проблема, так как проверка DNS является асинхронной, то код продолжает выполнение закрытия потока. Когда ответ DNS наконец приходит, он не может писать нигде. Я уже пытался использовать асинхронный модуль, но он не работал. Вероятно, я сделал что-то не так.

Любая идея?

+0

Обещания существуют для решения проблемы, с которой вы сталкиваетесь. Я бы посмотрел на что-то вроде https://github.com/kriszyp/promised-io – inkdeep

+0

. Замечание: я довольно уверен, что вы имели в виду 'if (err)', а не 'if (! Err)' выше, поскольку блок, подключенный к нему, предназначен для обработки ошибки. –

ответ

2

Теперь, когда NodeJS в основном до скорости с функциями ES2015 (и я замечаю, что вы используете по крайней мере, одну функцию стрелки), вы можете использовать собственные обещания в JavaScript (ранее вы могли бы использовать библиотеку):

var stream = fs.createWriteStream("my_file.txt"); 
stream.once('open', function(fd) { 
    Promise.all(names.map(name => doSomething(name))) 
    .then(() => { 
    // success handling 
    stream.end(); 
    }) 
    .catch(() => { 
    // error handling 
    stream.end(); 
    }); 
}); 

(линия Promise.all(names.map(name => doSomething(name))) может быть просто Promise.all(names.map(doSomething)), если вы знаете doSomething игнорирует дополнительные аргументы и использует только первый.)

Promise.all (spec | MDN) принимает итерабельность и возвращает обещание, которое разрешается, когда все обещания в итерабеле разрешены (значения без обетования рассматриваются как разрешенные обещания с использованием значения в качестве разрешения).

Где doSomething становится:

function doSomething(name) { 
    return new Promise((resolve, reject) => { 
    dns.lookup(domain, (err, addresses, family) => { 
     if(!err){       // <== You meant `if (err)` here, right? 
     stream.write("Error:", err); 
     reject(/*...reason...*/); 
     }else{ 
     stream.write(addresses); 
     resolve(/*...possibly include addresses*/); 
    }); 
    }); 
}); 

Существует различный ЛИЭС, что будет «обещание-римент» обратные вызовы Node-стиль для вас, так с помощью обещаний менее неуклюжие, чем выше смесей; в этом случае вы могли бы использовать обещание от обещания dns.lookup напрямую, а не создавать свой собственный дополнительный.

+0

Это отлично работает! благодаря – Nahoot

Смежные вопросы