Как цикл ответа на запрос в узле js работает с внешним вводом-выводом
Завершите вводный файл node.js здесь. Я видел этот пример "Привет, мир" где-то
// Load the http module to create an http server.
var http = require('http');
// Configure our HTTP server to respond with Hello World to all requests.
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello World\n");
});
// Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8000);
// Put a friendly message on the terminal
console.log("Server running at http://127.0.0.1:8000/");
Действительно простой код, в котором сервер отвечает на HTTP-запросы простым HTTP-ответом с простым текстом "Hello World"
Я также готов о библиотеке, чтобы сделать HTTP-запросы из JavaScript
http.get(options, function(resp){
resp.on('data', function(chunk){
//do something with chunk
});
}).on("error", function(e){
console.log("Got error: " + e.message);
});
Здесь вы делаете HTTP-запрос с некоторыми опциями, а затем делаете что-то с ответом в обратном вызове.
Что делать, если сделать такой запрос API, когда HTTP-запрос поступает на сервер node.js? Поскольку поток должен быть однопоточным, как можно изменить состояние ответа, отправляемого клиенту node.js при обратном вызове HTTP-запроса API? Не будет ли ответ уже отправлен к циклу событий? Как можно симулировать синхронные запросы в этой системе, чтобы вы могли использовать ответ на запрос API для отправки ответа клиенту?
2 ответа
Поскольку поток должен быть однопоточным, как можно изменить состояние ответа, отправляемого клиенту node.js при обратном вызове HTTP-запроса API?
Потому что ответ не отправляется синхронно с полученным запросом.
Не будет ли ответ уже отправлен к циклу событий?
Ответ не будет отправлен, пока вы не позвоните res.send
или аналогичный, который не обязательно должен находиться в том же задании из очереди заданий, которое вызвало обратный вызов вашего запроса - и часто это не так.
Как можно симулировать синхронные запросы в этой системе, чтобы вы могли использовать ответ на запрос API для отправки ответа клиенту?
Там нет необходимости, и это убило бы пропускную способность.
В любом конкретном потоке (а NodeJS использует только один) JavaScript работает на основе очереди заданий: единственный поток JavaScript работает, отбирая задание из очереди, выполняя весь код для него, а затем подбирая следующее задание из очереди (или в режиме ожидания, пока оно не будет добавлено). Когда приходит событие или подобное, если вы настроили обработчик для этого события, вызов вашего обработчика добавляется в очередь заданий. (На самом деле в очереди заданий минимум два слоя; см. Этот ответ, если вам интересно.)
Совершенно нормально, если вы не отвечаете на "Мы получили HTTP-запрос" из кода для задания, которое вызвало ваш обработчик. Это совершенно нормально. Работа и просьба полностью отделены друг от друга. И поэтому это нормально (и нормально), если вы запускаете асинхронный процесс (например, get
или readFile
). Позже, когда результат этого процесса станет доступен, новое задание будет добавлено в очередь, поток JavaScript заберет его, и вы используете res.send
или аналогичный, чтобы ответить на ожидающий запрос.
Вот как NodeJS управляет высокой пропускной способностью, несмотря на наличие только одного потока: если вы используете асинхронный ввод-вывод повсеместно, ваш реальный код не должен занимать поток все это время, потому что он не ожидает ввода-вывода завершить. Он может выполнять больше работы над другими вещами во время ожидания ввода-вывода, а затем отвечать на него после завершения ввода-вывода.
Вы должны изменить свой код следующим образом:
http.get(options, function(resp){
resp.on('data', function(chunk){
resp.send(chunk);
});
}).on("error", function(e){
console.log("Got error: " + e.message);
});