Вы сделали несколько недостатков.
Вы должны переписать раскрытие, чтобы передать URL и передать обратный вызов. Любая функция, которая делает что-либо асинхронное, обычно имеет подпись (data, callback)
в узле. Это в основном позволяет вам сказать, что я хочу, чтобы эта функция что-то сделала, а затем сказать мне, когда это будет сделано.
function expand(urlToParse, callback) {
// note we pass in the url this time
var short = url.parse(urlToParse);
var options = {
host: short.hostname,
port: 80,
path: short.pathname
};
// note we store the clientRequest object temporarily
var clientRequest = http.get(options, extractRealURL);
// Always attach the error handler and forward any errors
clientRequest.on("error", forwardError);
function extractRealURL(res) {
callback(null, res.headers.location);
}
function forwardError(error) {
callback(err);
}
}
Здесь обратный вызов, как ожидается, будет иметь подпись (err, data)
, которую имеют почти все обратные вызовы в узле. Мы также добавили обработку ошибок, которая является обязательной.
Теперь мы изменили onRequest, чтобы фактически вызвать расширение должным образом
function onRequest(request, response) {
// parse the incoming url. true flag unpacks the query string
var parsedUrl = url.parse(request.url, true),
// extract the querystring url.
// http://localhost:8888/?url=http://t.co/wbDrgquZ
urlToExpand = parsedUrl.query.url;
// call expand with the url and a callback
expand(urlToExpand, writeResponse);
function writeResponse(error, newUrl) {
// handle the error case properly
if (error) {
response.writeHead(500, { 'Content-Type': 'text/plain'});
// early return to avoid an else block
return response.end(error.message);
}
response.writeHead(200, { 'Content-Type': 'text/plain'});
// write the new url to the response
response.end(newUrl);
}
}
Здесь мы добавили логику обработки ошибок, а также распаковали фактический URL для расширения из строки запроса.
Обычно шаблон doSomething<data, callback<err, result>>
очень хорошо работает в файле node.js.
Это то же самое, что и let result = doSomething<data> mayThrow err
, которое вы ожидаете от обычных языков блокировки, кроме асинхронных.
Обратите внимание, что альтернативная опция передачи объекта ServerResponse
в функцию не одобряется, тем самым создавая ненужную жесткую связь между функцией расширения и ответом сервера.
Функция раскрытия должна только расширять URL-адрес и возвращать расширенный URL-адрес, не имеет никакого отношения к IO.
Полный код