2016-05-31 16 views
0

Was ich tue ist fs, um 5 Stücke von HTML-Seite Teile (html, head, chead, topaside, main, footer) zusammen zu sticken. Der Dateiname lautet htmlpage.js, Sie können also einfach node htmlpage.js file1 file2 file3 ... im Befehlszeilentool ausführen, und diese HTML-Page-Teile zusammenheften, dann spucken Sie file1.html, file2.html, file3.html ... aus. Ich mag es nicht, Vorlagen-Engine/Bibliothek/Framework oder was auch immer zu verwenden, besonders wenn ich lerne.
Hier ist der sorce Code:Node.js wie mit async Callback zu iterieren?

'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}); 
} 

Was aber, wenn die htmlray 100 Teile hat, ich will es sich pipeblock nennen können, eine Iteration zu tun, diese Codes zu ersetzen, lassen:

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'); 
        }); 
       }); 
      }); 
     }); 
    }); 

habe ich versucht, diese Lösungen, die sie nicht arbeiten:
Lösung 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. 

Lösung:

//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 

Antwort

0

Während ich Async durchliest und Dokumentation verspreche, komme ich zum Teil über Parallele, Serie und Wasserfall. Mein Problem ist das Erstellen einer HTML-Seite, so dass es nicht parallel gemacht werden kann. Aber die Dokumentation beginnt und redet viel von Parallelen, und sie fügen meinem Kopf nur Verwirrung hinzu. Um alle zu erfassen, wird es wahrscheinlich lange dauern. Wie auch immer, während ich experimentiere, habe ich eine einfache Lösung gefunden.
In mein Problem ist das sich wiederholende Teil über prüfen, ob vorherige HTML-Teil schriftlich getan hat readingStream.on('end', <do next writing>); unter Verwendung, so dass ich es in eine Funktion:

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

Dann kann ich pipeblock in drehen:

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); 

Dann kann ich eine Iteration in einer Funktion tun:

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; 
} 

Jetzt kann ich ersetzen pipeblock mit thi s:

1

Dieses Ding Anrufe „Rückruf Hölle“ und Sie sollten einige Bibliothek verwenden entweder Asynchron-Anrufe wie async.js oder (besser) verwenden Versprechen zu behandeln.

Einfach nur fs.readFile wie diese promisify (oder Ihr eigenes Versprechen schreiben für fs.createReadStream es Sie es benutzen wollen)

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

und dann Ihre Anfrage Versprechen kombinieren Promise.all()

Hier sind einige Beispiele mit http://bluebirdjs.com/docs/api/promise.promisify.html, http://bluebirdjs.com/docs/api/promise.all.html für fs für Bluebird-Versprechen-Bibliothek.

+0

Ja, ich habe einige Videos geschaut und von Zeit zu Zeit die Dokumentation über Versprechen und Generator gelesen, aber ich habe sie jedes Mal entlassen. Nun, wenn sie die einzige Lösung, aber keine Iteration sind, muss ich sie ausprobieren. Danke für die Erinnerung. – alexcres

+0

Ich selbst habe vor ein oder zwei Jahren viel Zeit verloren, um dieses Zeug zu überspringen (und ich bereue es wirklich) und versuche, mit Callback Loops, asynchronen Wasserfällen usw. zu experimentieren - Versprechen sind elegant und kraftvoll. Und schon mit der Fehlerbehandlung (das sollte auch wichtig sein) - füge einfach '.catch()' zu deinem endgültigen Versprechen hinzu. –

+0

Waite, ich erinnere mich nur, dass für meine Frage von async Callback 100 Mal, in Aussicht, Sie müssen dann() für den nächsten Anruf 100 Mal verwenden. Und im Generator müssen Sie immer noch 100 Mal nachgeben. Habe ich recht? Ich will das nicht wirklich machen. – alexcres