需要在操作完成后发送响应
Need to send response after an action has completed
我正在尝试制作一个网络爬虫,它可以爬取 IMDB 并列出电影名称和评级。这是我的 index.js 文件。
假设我正在抓取 10 部电影。然后我将抓取的结果保存在另一个文件中,比如 'message.txt'。现在我想发送此 message.txt 文件作为对任何请求的响应。但是每当我发出请求时,它总是首先向我的浏览器发送一个空文件。然后我注意到抓取的结果需要一些时间才能保存在 message.txt 文件中。我认为这是因为在 nodejs 中所有操作都是异步的。那么有没有办法在抓取完成后才发送message.txt文件呢?
var express = require('express');
var app = express();
var cheerio = require('cheerio');
var request = require('request');
var fs = require('fs');
app.listen(8080);
console.log('Running');
app.get('/', function(req, res) {
console.log('Recieved the get Request');
var i = 1;
var count = 0;
while (count < 10) {
var url = 'http://www.imdb.com/title/tt' + i + '/';
console.log(url);
count = count + 1;
i = i + 1;
request(url, function(error, response, html) {
if (!error) {
var $ = cheerio.load(html);
var title, ratings, released;
var json = {
title: '',
ratings: '',
released: ''
};
$('.title_wrapper').filter(function() {
var data = $(this);
json.title = data.children().first().text().trim();
json.released = data.children().last().children().last().text().trim();
});
$('.ratingValue').filter(function() {
var data = $(this);
json.ratings = parseFloat(data.text().trim());
});
console.log(json);
fs.appendFile('message.txt', JSON.stringify(json, null, 4) + '\n', function(err) {});
};
});
};
res.sendFile(__dirname + '/index.js');
});
fs.appendFile('message.txt', JSON.stringify(json, null, 4) + '\n', function(err) {
//This part is executed after the process has been completed
});
您必须在那里进行回调,因为该部分只会在您的操作执行后调用。
我们在这里使用了回调功能,尽管在我们的例子中除了 err 之外没有任何具体的回调,但我们不需要任何其他的回调。
请尝试。
fs.appendFile()
是异步的,因此当函数 returns 时,您附加到文件的内容不会立即存在。因此,如果您想要阅读并将该文件发送给用户,您需要在提供给 fs.appendFile()
的回调中执行此操作。
app.get('/', function(req, res) {
...
fs.appendFile(
'message.txt',
JSON.stringify(json, null, 4) + '\n',
function(err) {
if (err) {
// Log the error and send a message to the user here
return;
}
res.sendFile(__dirname + '/index.js')
}
);
};
});
};
});
您可能想改用 fs.appendFileSync()
。这对于命令行工具来说没问题,但由于这是一个 Web 服务器,所以不要那样做。它会在 I/O 发生时锁定线程。
您可以使用非常适合控制流程的异步包,例如:
console.log('Recieved the get Request');
var i = 1;
var count = 0;
while (count < 10) {
var url = 'http://www.imdb.com/title/tt' + i + '/';
console.log(url);
count = count + 1;
i = i + 1;
async.waterfall([
function sendRequest (callback) {
if (!error) {
var $ = cheero.load(html);
var json = {
title: '',
ratings: '',
released: ''
}
}
$('.title_wrapper').filter(function() {
var data = $(this);
json.title = data.children().first().text().trim();
json.released = data.children().last().children().last().text().trim();
});
$('.ratingValue').filter(function() {
var data = $(this);
json.ratings = parseFloat(data.text().trim());
});
callback(null, JSON.stringify(json, null, 4) + '\n');
},
function appendFile (json, callback) {
fs.appendFile('message.txt', json, function(err) {
if (err) { callback(err); }
callback();
});
}
], function(err) {
res.sendFile(__dirname + '/index.js');
});
我正在尝试制作一个网络爬虫,它可以爬取 IMDB 并列出电影名称和评级。这是我的 index.js 文件。 假设我正在抓取 10 部电影。然后我将抓取的结果保存在另一个文件中,比如 'message.txt'。现在我想发送此 message.txt 文件作为对任何请求的响应。但是每当我发出请求时,它总是首先向我的浏览器发送一个空文件。然后我注意到抓取的结果需要一些时间才能保存在 message.txt 文件中。我认为这是因为在 nodejs 中所有操作都是异步的。那么有没有办法在抓取完成后才发送message.txt文件呢?
var express = require('express');
var app = express();
var cheerio = require('cheerio');
var request = require('request');
var fs = require('fs');
app.listen(8080);
console.log('Running');
app.get('/', function(req, res) {
console.log('Recieved the get Request');
var i = 1;
var count = 0;
while (count < 10) {
var url = 'http://www.imdb.com/title/tt' + i + '/';
console.log(url);
count = count + 1;
i = i + 1;
request(url, function(error, response, html) {
if (!error) {
var $ = cheerio.load(html);
var title, ratings, released;
var json = {
title: '',
ratings: '',
released: ''
};
$('.title_wrapper').filter(function() {
var data = $(this);
json.title = data.children().first().text().trim();
json.released = data.children().last().children().last().text().trim();
});
$('.ratingValue').filter(function() {
var data = $(this);
json.ratings = parseFloat(data.text().trim());
});
console.log(json);
fs.appendFile('message.txt', JSON.stringify(json, null, 4) + '\n', function(err) {});
};
});
};
res.sendFile(__dirname + '/index.js');
});
fs.appendFile('message.txt', JSON.stringify(json, null, 4) + '\n', function(err) {
//This part is executed after the process has been completed
});
您必须在那里进行回调,因为该部分只会在您的操作执行后调用。
我们在这里使用了回调功能,尽管在我们的例子中除了 err 之外没有任何具体的回调,但我们不需要任何其他的回调。
请尝试。
fs.appendFile()
是异步的,因此当函数 returns 时,您附加到文件的内容不会立即存在。因此,如果您想要阅读并将该文件发送给用户,您需要在提供给 fs.appendFile()
的回调中执行此操作。
app.get('/', function(req, res) {
...
fs.appendFile(
'message.txt',
JSON.stringify(json, null, 4) + '\n',
function(err) {
if (err) {
// Log the error and send a message to the user here
return;
}
res.sendFile(__dirname + '/index.js')
}
);
};
});
};
});
您可能想改用 fs.appendFileSync()
。这对于命令行工具来说没问题,但由于这是一个 Web 服务器,所以不要那样做。它会在 I/O 发生时锁定线程。
您可以使用非常适合控制流程的异步包,例如:
console.log('Recieved the get Request');
var i = 1;
var count = 0;
while (count < 10) {
var url = 'http://www.imdb.com/title/tt' + i + '/';
console.log(url);
count = count + 1;
i = i + 1;
async.waterfall([
function sendRequest (callback) {
if (!error) {
var $ = cheero.load(html);
var json = {
title: '',
ratings: '',
released: ''
}
}
$('.title_wrapper').filter(function() {
var data = $(this);
json.title = data.children().first().text().trim();
json.released = data.children().last().children().last().text().trim();
});
$('.ratingValue').filter(function() {
var data = $(this);
json.ratings = parseFloat(data.text().trim());
});
callback(null, JSON.stringify(json, null, 4) + '\n');
},
function appendFile (json, callback) {
fs.appendFile('message.txt', json, function(err) {
if (err) { callback(err); }
callback();
});
}
], function(err) {
res.sendFile(__dirname + '/index.js');
});