2014-02-19 11 views
9

Ich versuche, mich um Generatoren und Ertrag in JavaScript und Node.js, aber mit einem Problem.Wrapping fs.readFile in einem Generator/Ausbeute

Idealerweise möchte ich fs.readFile mit generators/yield umschließen, damit ich es synchron verwenden kann, ohne etwas zu blockieren.

Ich habe mit dem folgenden Code kommen:

function readFileSync (path) { 
    return (function *(){ 
     return yield require('fs').readFile(path, function *(err, data){ 
      yield data; 
     }); 
    })(); 
} 

console.log(readFileSync('test-file.txt')); 

Aber leider readFileSync nur gibt immer {} anstelle des Dateiinhalts.

Hoffentlich ist das, was ich erreichen möchte, noch möglich, oder ich habe den Punkt der Generatoren/Ausbeute völlig verpasst und ich benutze es völlig falsch, in welchem ​​Fall ich darauf hinwies, wo ich falsch gelaufen bin und irgendwelche Ressourcen wäre großartig.

+0

In allen Generator-Beispielen habe ich gesehen, waren Versprechungen beteiligt. Auf welchen Docs/Posts/Howtos basiert dein Skript? – Bergi

+0

Warum nicht einfach 'fs.readFileSync' verwenden? – Bergi

+1

'Warum nicht einfach fs.readFileSync verwenden?' Es blockiert. Der Anwendungsfall hier ist, diese Zeile nicht blockierend zu machen: https://github.com/bevry/ssg-experiments/blob/aba629383d0945fffc843e2d43c4b180ca0083bd/index.js#L24 – balupton

Antwort

-3

Es ist nicht möglich, eine asynchrone Funktion in eine synchrone Funktion mit Generatoren umzuwandeln.

Generatoren können sich selbst unterbrechen, aber sie können den Steuerungsfluss anderer Funktionen nicht unterbrechen.

So ist die einzige Art und Weise, wie Ihr Code kann, ist, funktionieren, wenn es in einem anderen Generator ist:

console.log(yield* readFileSync('test-file.txt')); 
1

Sie können einen Helfer lib wie Wait.for-ES6 verwenden (ich bin der Autor)

Pro : Sie können beliebige Standard-Asynchron node.js

Con Funktion nacheinander nennen: Sie ca n tun es nur in einem Generator function*

Beispiel mit fs.readdir und fs.readfile (beide sind Standard Asynchron node.js Funktionen)

var wait=require('wait.for-es6'), fs=require('fs'); 

function* sequentialTask(){ 
    var list = yield wait.for(fs.readdir,'/home/lucio'); 
    console.log(list); // An array of files 
    var data = yield wait.for(fs.readFile,list[0]); //read first file 
    console.log(data); // contents 
} 

wait.launchFiber(sequentialTask); 
10

Wie wäre es mit Knoten mit Harmonie aktiviert Funktionen (node --harmony) und das Super Einfaches ES6-Schnipsel:

function run(gen, iter) { 
    (iter=gen((err, data) => (err && iter.raise(err)) || iter.next(data))).next(); 
} 

run(function* (resume) { 
    var contents = yield require('fs').readFile(path, resume); 
    console.log(contents); 
}); 

Sie können mehr über dieses tote einfache Muster lesen (und es online ausprobieren) an diesem Artikel

function run(gen) { 
    var iter = gen(function (err, data) { 
    if (err) { iter.throw(err); } 
    return iter.next(data); 
    }); 
    iter.next(); 
} 

run(function* (resume) { 
    var contents = yield require('fs').readFile(path, resume); 
    console.log(contents); 
}); 

Danke lgersman: bei orangevolt.blogspot.com

1

Nur ein bisschen desugerifying und update (scheint raise zu throw umbenannt wird) lgersman's Antwort darauf mit io.js 1.0.4 funktioniert!