POST Körper in Node.js und einige asynchrone Zustandsprüfung
-
25-09-2019 - |
Frage
Ich möchte Anfrage (POST) Körper von http.ServerRequest
zu bekommen, aber tun so nicht gerade, wenn meine Anfrage Funktion aufgerufen wird, aber erst nach einiger Zeit (Redis Abfrage).
Ich habe ein sehr einfaches Beispiel zur Veranschaulichung:
var http = require('http'),
sys = require('sys');
http.createServer(function (req, res) {
sys.puts("Got request");
req.pause();
setTimeout(function() { // In real code I'm accessing Redis here.
var body = "";
req.addListener('data', function (chunk) {
sys.puts("Got 'data' event");
body += chunk;
});
req.addListener('end', function () {
sys.puts("Got 'end' event");
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(body);
});
req.resume();
}, 10);
}).listen(8000);
In diesem Beispiel data
und end
Ereignisse völlig verfehlt werden, obwohl ich req.pause()
/ req.resume()
bin Aufruf, so Wunsch des "stecken".
Wenn ich setTimeout()
Anruf Kommentar und alles tun, gerade in Anforderungsfunktion, alles funktioniert wie erwartet. Aber ich will Redis abfragen, wenn die Anforderung die gültig anzusehen. Die Pfosten sind große Datei-Uploads, und ich möchte nicht, Zeit verschwenden für erfolglose Upload auf vollständige warten.
Der einfache Weg, dies zu tun ist, um die POST für einige Millisekunden Verzögerung (in meinem Fall POSTs zumindest einige Sekunden dauern würde, so solche winzige Verzögerung ziemlich unbedeutend ist). Die sauberere ist eingehende Daten-Parsing zu starten, gleichzeitig die Anforderung zu validieren und die Verbindung fallen, wenn Wunsch des gefunden ungültig.
Die Frage ist: Wie ich irgendetwas davon tun würde? Ich verwende Node.js Version 0.1.97-14-g0055dd1 wenn diese Angelegenheiten.
Vielen Dank für alle Vorschläge.
Lösung
Sie wissen nicht, wann immer ich das richtig mache, aber das scheint das Richtige für mich:
var http = require('http'),
sys = require('sys');
http.createServer(function (req, res) {
var body = "",
body_complete = false,
wait_complete = false;
sys.debug("Got request");
// This will be called on each process' completion
var final_cb = function(err) {
if (err) throw new Error(err);
if (body_complete && wait_complete) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(body);
}
};
// Async process one: get POST body
req.addListener('data', function (chunk) {
sys.debug("Got 'data' event");
body += chunk;
});
req.addListener('end', function () {
sys.debug("Got 'end' event");
body_complete = true;
final_cb(null)
});
// Async process two: wait 10ms
setTimeout(function() { // In real code I'm accessing Redis here.
sys.debug("Timeout passed");
if (false) { // Okay, timeout can't go wrong
res.writeHead(403);
res.end('Sorry');
}
wait_complete = true;
final_cb(null);
}, 10);
}).listen(8000);
Addition: Wenn Connect Middleware einige asynchrone Anfragen ausführen möchte (das heißt die Steuerung zurück zu der Ereignisschleife passieren) es funktioniert um auf diese Weise:
var pause = utils.pause(req);
fs.readFile(path, function(){
next();
pause.resume();
});
Wo utils.pause()
ein Hack zu puffern Ereignisse anhängig .