【问题标题】:Need to send response after an action has completed需要在操作完成后发送响应
【发布时间】:2016-02-28 21:55:36
【问题描述】:

我正在尝试制作一个网络爬虫,它可以爬取 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');
});

【问题讨论】:

  • 使用 promises - 回调,当 fs 流完成保存文件时调用发送文件。
  • 你能否解释更多@GandalftheWhite

标签: node.js asynchronous web-crawler imdb


【解决方案1】:

您可以使用非常适合控制流程的 async 包,例如:

  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');
    });

【讨论】:

【解决方案2】:
fs.appendFile('message.txt', JSON.stringify(json, null, 4) + '\n', function(err) {
//This part is executed after the process has been completed 
});   

您必须在那里进行回调,因为该部分仅在您执行操作时才会被调用。

我们在这里使用了回调功能,尽管在我们的例子中除了错误之外没有任何具体的回调,但我们不需要任何其他的严重。

请尝试。

【讨论】:

    【解决方案3】:

    fs.appendFile() 是异步的,因此当函数返回时,您附加到文件的内容不会立即出现。因此,如果您想读取将该文件发送给用户,则需要在您提供给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 发生时锁定线程。

    【讨论】:

    • 每个 request() 将返回 1 个 json。假设我调用request() 10 次,那么在将res.sendFile 写入一次message.txt 文件后可能会发生这种情况。所以剩下的 9 个 json 没有附加。那么如何确保在进行所有request() 调用之后,只有文件会发送到浏览器
    猜你喜欢
    • 2015-12-22
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    • 2019-03-04
    • 2020-02-16
    • 1970-01-01
    相关资源
    最近更新 更多