2016-05-31 4 views
0

То, что я делаю, используется fs, чтобы сшить 5 частей html-страниц (html, head, chead, topaside, main, footer) вместе. Имя файла: htmlpage.js, поэтому вы можете просто запустить node htmlpage.js file1 file2 file3 ... в инструменте командной строки, и он будет сшивать эти части html-страницы вместе, а затем выплюнуть file1.html, file2.html, file3.html .... Я не люблю использовать механизм шаблонов/библиотеку/фреймворк или что-то еще, особенно когда я учусь.
Вот код Sorce:Node.js, как итерации с асинхронным обратным вызовом?

'use strict'; 
const fs = require('fs'), 
     head = fs.createReadStream('./html-parts/head.html', 'utf8'), 
     topaside = fs.createReadStream('./html-parts/topaside.html', 'utf8'), 
     footer = fs.createReadStream('./html-parts/footer.html', 'utf8'); 

let name = process.argv.slice(2), 
    htmlray = [], 
    ni = 0, 
    nl = name.length; 
for (ni; ni < nl; ni ++) { 
    let cheadP = './html-parts/' + name[ni] + '-head.html', 
     mainP = './html-parts/' + name[ni] + '-main.html', 
     htmlP = name[ni] + '.html', 
     chead = fs.createReadStream(cheadP, 'utf8'), 
     main = fs.createReadStream(mainP, 'utf8'), 
     html = fs.createWriteStream(htmlP, 'utf8'); 
    //let those parts form an array 
    htmlray = [html, head, chead, topaside, main, footer]; 
    openendPipe(htmlray[1], htmlray[0]); 
    htmlray[1].on('end',() => { 
     openendPipe(htmlray[2], htmlray[0]); 
     htmlray[2].on('end',() => { 
      openendPipe(htmlray[3], htmlray[0]); 
      htmlray[3].on('end',() => { 
       openendPipe(htmlray[4], htmlray[0]); 
       htmlray[4].on('end',() => { 
        htmlray[5].pipe(htmlray[0]); 
        htmlray[5].on('end',() => { 
         console.log(name + '.html' + ' created'); 
        }); 
       }); 
      }); 
     }); 
    }); 
} 
function openendPipe(src, dst) { 
    return src.pipe(dst, {end: false}); 
} 

Но что, если htmlray имеет 100 частей, я хочу, чтобы иметь возможность делать итерации, чтобы заменить эту коду, давайте назовем его pipeblock:

openendPipe(htmlray[1], htmlray[0]); 
    htmlray[1].on('end',() => { 
     openendPipe(htmlray[2], htmlray[0]); 
     htmlray[2].on('end',() => { 
      openendPipe(htmlray[3], htmlray[0]); 
      htmlray[3].on('end',() => { 
       openendPipe(htmlray[4], htmlray[0]); 
       htmlray[4].on('end',() => { 
        htmlray[5].pipe(htmlray[0]); 
        htmlray[5].on('end',() => { 
         console.log(name + '.html' + ' created'); 
        }); 
       }); 
      }); 
     }); 
    }); 

Я пробовал эти решения, они не работали:
решение 1:

(function() { 
    let i = 0, count = 1; 
    function nextpipe() { 
     let arr = arguments[0]; 
     i ++; 
     if (count > 5) return; 
     openendPipe(arr[i], arr[0]); 
     count ++; 
     arr[i].on('end', nextpipe); 
      } 
    return nextpipe; 
})(); 
//then replace 'pipeblock' with 'nextpipe(htmlray)'; 
//console.log: nextpipe is undefined. 

Решение 2:

//replace 'pipeblock' with these code 
let pi = 1, 
    pl = htmlray.length - 1; 
htmlray[pi].pipe(htmlray[0], {end: false}); 
htmlray[pi].on('end', nextpipe); 
function nextpipe() { 
    if (pi > pl) return console.log(name + '.html' + ' created');; 
    pi ++; 
    htmlray[pi].pipe(htmlray[0], {end: false}); 
    htmlray[pi].on('end', nextpipe); 
} 
//cosole.log: 
//htmlray[pi].pipe(htmlray[0], {end: false}); 
//TypeError: Cannot read property 'pipe' of undefined 

ответ

0

Пока я читаю асинхронную документацию и обещаю документацию, я добираюсь до части о параллели, серии и водопаде. Моя проблема заключается в создании html-страницы, поэтому ее нельзя выполнить параллельно. Но документация начинается и много говорит о параллельности, и они просто добавляют путаницу в мою голову. Ухватить все из них, вероятно, займет много времени. Во всяком случае, пока я экспериментирую, я придумываю простое решение.
В моей проблеме, повторяющаяся часть о проверке, если предыдущий HTML-часть сделал писать с помощью readingStream.on('end', <do next writing>);, поэтому я делаю его в функцию:

function ifend(src, src2, dst) { 
    return src.on('end',() => {return openendPipe(src2, dst);}); 
} 

Тогда я могу превратить pipeblock в:

openendPipe(htmlray[0], html); 
ifend(htmlray[0], htmlray[1], html); 
ifend(htmlray[1], htmlray[2], html); 
ifend(htmlray[2], htmlray[3], html); 
ifend(htmlray[3], htmlray[4], html); 

Тогда я могу сделать итерацию в функции:

function createHtml(src, dst) { 
    let l = src.length - 1, 
     i = 0; 
    openendPipe(src[0], dst); 
    for (i; i < l; i ++) { 
     //iterate ifend function. 
     ifend(src[i], src[i + 1], dst); 
    } 
    return dst; 
} 

Теперь я могу заменить pipeblock с Тхи s:

createHtml(htmlray, html); 
1

Этой вещь называет «обратный вызов ад», и вы должны использовать либо некоторую библиотеку для обработки асинхронных вызовов, как async.js или (лучше) использовать обещание.

Просто promisify fs.readFile как это (или написать собственное обещание для fs.createReadStream это вы хотите использовать)

const readFile = Promise.promisify(require('fs').readFile); 

, а затем объединить ваш запрос обещания используя Promise.all()

Вот примеры http://bluebirdjs.com/docs/api/promise.promisify.html, http://bluebirdjs.com/docs/api/promise.all.html для fs для библиотеки обещаний Bluebird.

+0

Да, я смотрел пару видеороликов и время от времени читал документацию о обещании и генераторе, но каждый раз я их увольнял. Ну, если это единственное решение, но не итерация, я думаю, я должен попробовать их. Спасибо за напоминание. – alexcres

+0

Я потерял много времени сам год или два назад, пытаясь пропустить этот материал (и я действительно сожалею об этом), и пытаюсь поэкспериментировать с циклами обратного вызова, асинхронными водопадами и т. Д. - обещания - изящное и мощное решение. И уже с обработкой ошибок (это также должно быть важно) - просто добавьте '.catch()' к вам окончательное обещание. –

+0

Waite, я просто помню, что для моего вопроса об асинхронном обратном вызове 100 раз, в обещании, вам все равно нужно использовать then() для следующего вызова 100 раз. А в генераторе вам все равно нужно получить 100 раз. Я прав? Я действительно не хочу этого делать. – alexcres

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