2016-02-28 67 views
0

我正在嘗試製作抓取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'); 
 
});

+0

使用的承諾 - 回調,當FS流完成後保存文件撥打電話發送文件。 –

+0

你可以解釋更多@GandalftheWhite – Mohit

+0

我希望可以幫助 –

回答

0

可以使用異步包,它是偉大的控制流量,喜歡的東西:

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

是否使用'async'並行包。找到這個鏈接非常有用[在所有異步請求被調用並執行後執行某個函數](http://stackoverflow.com/a/16866080/3717234) – Mohit

0
fs.appendFile('message.txt', JSON.stringify(json, null, 4) + '\n', function(err) { 
//This part is executed after the process has been completed 
}); 

你必須做一個回調那裏該部分將在已執行的操作只調用。

我們利用這裏的回調函數,雖然沒有任何具體的回調,除了我們的情況下的err,我們並不需要其他任何其他的。

請嘗試。

0

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時鎖定線程。

+0

每個'request()'將返回1個json。假設我調用request()10次,那麼在寫入message.txt文件之後可能會發生'res.sendFile'被觸發。所以剩下的9個jsons不會被追加。所以如何確保在所有的request()調用完成之後,只有文件會被髮送到瀏覽器 – Mohit

相關問題