2016-07-10 4 views
0

Ich versuche, eine curried Fn mit einer Schließung als Rückruf zu den Servern request event zu verwenden.Wie funktioniert der Rückruf zum Server "Anfrage-Event" in node.js?

Es funktioniert das erste Mal, wenn ein Client eine Anfrage (das HTML wird gesendet und angezeigt), aber das zweite Mal, dass die Seite leer ist. Löscht Knoten den Abschluss nach dem ersten Aufruf des cb?

// server.js 
var pype = function(self, arr, errorHandler, cb) { 
    var i = 0, 
    req, 
    res, 
    run = function() { 
    arr[i].call(self, req, res, next); 
    }, 
    next = function(err) { 
    if (err && errorHandler) { 
     return errorHandler.call(self, err, req, res); 
    } 
    i++ 
    if (i < arr.length) { 
     return run(); 
    } else if (cb) { 
     return cb.call(self, req, res); 
    } 
    } 

    return function(request, response) { 
    req = request; 
    res = response; 
    run(); 
    } 
}; 

var http = require("http”); 
var server = http.createServer(); 
var errorhandler = function(err, req, res) { 
    res.end(err); 
}, 
var finalHandler = function(req, res) { 
    res.setHeader("Content-Type", "text/html"); 
    res.end(req.html); 
}; 
var requestHandler = pype(null, [pens, gits, concat, index, sort, html, finalHandler], errorhandler); 

// this works only once 
server.on('request', requestHandler); 

// this works for multiple calls 
server.on('request', function(req, res){ 
    var requestHandler = pype(null, [pens, gits, concat, index, sort, html, finalHandler], errorhandler); 
    requestHandler(req, res); 
}); 

Vielen Dank!

+2

einen besonderen Grund, warum Sie nicht nur 'Lauf machen()' 'akzeptieren request' und' response'? Sich zu sehr auf Schließung zu verlassen, macht unlesbaren Code. –

+0

@MadaraUchiha Sie haben Recht auf die Lesbarkeit. Dies ist nur ein Experiment. Ich glaube nicht, '' req'' und 'res' zu' run' zu übertragen, würde aber funktionieren. Sie werden auch im Körper von 'next' benötigt. –

Antwort

2

Knoten löscht keine Schließung.

Ich sehe aus wie Sie nie zurückgesetzt i zurück zu 0, wenn Sie mit einer Anfrage fertig sind oder eine neue Anfrage starten. Da der Abschluss seinen Zustand unbegrenzt beibehält, wenn die 2. Anfrage eingeht, zeigt i über das Ende des Arrays hinaus und Sie werden niemals irgendeine der Funktionen im Array aufrufen.

Sie können entweder i zurück auf 0 entweder bei einer Anfrage oder zu Beginn einer neuen Anfrage zurücksetzen.

Wechsel von dieser:

return function(request, response) { 
    req = request; 
    res = response; 
    run(); 
    } 

dazu:

return function(request, response) { 
    req = request; 
    res = response; 
    i = 0; 
    run(); 
    } 

, dass bestimmtes Problem zu beheben, aber Sie haben auch andere Probleme (siehe unten).


Es scheint, dass diese Struktur andere Probleme hat. Da Sie nur eine einzige Closure erstellen und diese dann für alle Anfragen erneut verwenden, werden die Abschlussvariablen der ersten Anfrage und der beiden Anfragen gelöscht, sobald Ihre erste Anfrage asynchron zur Verarbeitung von etwas geht und eine zweite Anfrage während dieser Zeit eintrifft kollidieren. Dieses Schema einer einzelnen permanenten Schließung ist ein unhaltbares Design für jeden Server, der jemals mehr als eine Anfrage gleichzeitig bearbeiten kann.

Ihr zweiter Versuch, der gut funktioniert, ist eine viel bessere Art, Dinge zu tun, weil Sie eine neue unabhängige Schließung für jede Anfrage erstellen, die das Race-Condition-Problem nicht haben wird, wenn mehrere Anfragen gleichzeitig fliegen.


Ich muss sagen, ich glaube wirklich nicht, dass der Curry-Stil hier überhaupt benötigt wird. Sie möchten keine dauerhafte Schließung schaffen, die auf unbestimmte Zeit bestehen bleibt (Sie brauchen für jede Anfrage eine neue). Und es macht Ihren Code viel schwieriger zu verstehen und zu folgen.


Es scheint mir viel einfacher, ohne die currying:

var http = require("http"); 
var server = http.createServer(); 

function handleRequest(ctx, req, res, handlers) { 
    return new Promise(function(resolve, reject) { 
     var i = 0; 

     function next(err) { 
      if (err) { 
       reject({err, req, res, ctx}); 
      } else { 
       run(); 
      } 
     } 

     function run() { 
      if (i < handlers.length) { 
       handlers[i++].call(ctx, req, res, next); 
      } else { 
       resolve({req, res, ctx}); 
      } 
     } 
     run(); 
    } 
} 

function errorhandler(info) { 
    info.res.end(info.err); 
} 

function finalHandler(info) { 
    info.res.setHeader("Content-Type", "text/html"); 
    info.res.end(req.html); 
} 


server.on('request', function(req, res) { 
    handleRequest(null, req, res, [pens, gits, concat, index, sort, html]).then(finalHandler, errorHandler); 
}); 
+0

Hallo @ jfriend00! Diese verdammten Inkrementoren. Vergessen Sie immer, sie zurückzusetzen Guten Fang! Du hast Recht mit dem Zirren. Wird überhaupt nicht benötigt. Nur ein Experiment, aber nicht besonders lesbar.Ich habe gerade versucht, ein paar Zeilen zu speichern, indem ich den requestHandler an das emit-Ereignis übergebe, anstatt an den Rumpf des Callbacks, aber wie Sie darauf hingewiesen haben, wird dies bei mehreren gleichzeitigen Anfragen kollidieren.TIL! Vielen Dank. Wirklich gut erklärt. Sie sollten darüber nachdenken zu lehren! : D –

Verwandte Themen