簡體   English   中英

如何在node.js非阻塞代碼中對代碼執行進行排序?

[英]How to sort a code execution in node.js Non-Blocking code?

我建立使用網絡爬蟲node.js ,但主要特征之一node.js ,是Non-Blocking代碼,這是偉大的,但對我來說這是破壞我的計划。 這是我的程序過去的工作方式:

  1. 首先,它request網站,並找到頁面上傳遞的所有公司的所有鏈接;
  2. 然后,我有for循環,用於修改該公司的URL數組;
  3. 然后,我有一個在for循環中的request ,該request將拋出公司URL數組以在每個公司頁面中查找所有產品URL;
  4. 然后有for循環,用於修改該產品的URL數組;
  5. 然后,我在for循環中有另一個請求,該請求拋出產品數組並獲取每個產品的價格,並將其存儲到dictionary(object)中,其中鍵是產品名稱,值是價格;
  6. 最后,我修改字典(對象)。

如您所見,我的每個步驟都取決於之前的步驟。 所以我需要做一些事情,使我的程序按照列出的順序運行。 我嘗試使用callback ,但是結局並不理想。 因為這是callback的簡單示例:

function some_function(arg1, arg2, callback) {
    var my_number = (arg1 - arg2) * arg2;
    callback(my_number);
}

some_function(20, 15, function(num) {
    console.log("callback called! " + num);
});

但是我不知道如何進行具有6個函數的回調。 也許有辦法,但是據我對callback的了解。 這是沒有callback的我的程序的演示版本:

var request = require('request');
var cheerio = require('cheerio');
var companiesUrls = [];
var url = '';
var companiesUrls2 = [];
var carsUrls = [];
var carsOwnerReview = {};
var carReviewUrl = [];
var site = '...'
var companiesPath = '/companies'
///step 1\\\
request(site+companiesPath, function(err, resp, body){
    if(!err && resp.statusCode == 200){
        var $ = cheerio.load(body);
        $('a', '#group-content').each(function(){
            var url = $(this).attr('href');
            companiesUrls.push(url);
        });
    };
});
///step 2\\\
for(var i=0;i<companiesUrls.length;i+=2){
    companiesUrls2.push(companiesUrls[i]);
};

///step 3\\\
for(var i=0;i<companiesUrls2.length;i++){
    request(site+companiesUrls2[i], function(err, resp, body){
        if(!err && resp.statusCode == 200){
            var $ = cheerio.load(body);
            $('h3.edition-title').children().children().each(function(){
                var url = $(this).attr('href');
                carsUrls.push(url);
            });
        };
    });
};
///step 4\\\
for(var i=0;i<carsUrls.length;i++){
    carReviewUrl.push(carsUrls[carsUrls.length-1].slice(0,-7)+'/owner-reviews');
};
///step 5\\\
for(var i=0;i<carReviewUrl.length;i++){
    request(site+carReviewUrl[i], function(err, resp, body){
        if(!err && resp.statusCode == 200){
            var $ = cheerio.load(body);
            var model = $('#page-title').text();
            $('span.total-votes').children().each(function(){
                var reviewNum = $(this).text();
                carsOwnerReview[model] = reviewNum;
            });
        };
    });
}
///step 6\\\
var keysSorted = Object.keys(carsOwnerReview).sort(function(a,b){return carsOwnerReview[a]-carsOwnerReview[b]});
var keysSortedReversed = keysSorted.reverse();

所以我的問題是: 我應該怎么做才能按順序使用node.js運行代碼?

如果您想使用JavaScript / node.js進行認真的編程,則必須深刻理解JS是異步的,除了代碼之外,所有其他事情都是並行發生的。

這意味着在您的情況下,除非所有代碼都已終止,否則不會調用回調。 因此,在for循環中調用異步函數應始終將所有警告燈變為紅色

這是正確設計的代碼:

var request = require('request');
var cheerio = require('cheerio');
var companiesUrls = [];
var url = '';
var companiesUrls2 = [];
var carsUrls = [];
var carsOwnerReview = {};
var carReviewUrl = [];
var site = '...'
var companiesPath = '/companies'


///step 1\\\
request(site+companiesPath, function(err, resp, body){
    if(!err && resp.statusCode == 200){
        var $ = cheerio.load(body);
        $('a', '#group-content').each(function(){
            var url = $(this).attr('href');
            companiesUrls.push(url);
        });
    };
    ///step 2\\\
    for(var i=0;i<companiesUrls.length;i+=2){
        companiesUrls2.push(companiesUrls[i]);
    };

    ///step 3\\\
    function processCompaniesUrls2( i, callback_pcu2 ) {
        if( i<companiesUrls2.length ) {
            request(site+companiesUrls2[i], function(err, resp, body){
                if(!err && resp.statusCode == 200){
                    var $ = cheerio.load(body);
                    $('h3.edition-title').children().children().each(function(){
                        var url = $(this).attr('href');
                        carsUrls.push(url);
                    });
                };
                processCompaniesUrls2( i+1, callback_pcu2 );
            });
        } else {
            callback_pcu2();
        }
    }
    processCompaniesUrls2( 0, function() {

        ///step 4\\\
        for(var i=0;i<carsUrls.length;i++){
            carReviewUrl.push(carsUrls[carsUrls.length-1].slice(0,-7)+'/owner-reviews');
        };
        ///step 5\\\
        function processCarReviewUrl( i, callback_pcru ) {
            if( i<carReviewUrl.length ) {
                request(site+carReviewUrl[i], function(err, resp, body){
                    if(!err && resp.statusCode == 200){
                        var $ = cheerio.load(body);
                        var model = $('#page-title').text();
                        $('span.total-votes').children().each(function(){
                            var reviewNum = $(this).text();
                            carsOwnerReview[model] = reviewNum;
                        });
                    };
                    processCarReviewUrl( i+1, callback_pcru );
                });
            } else {
                callback_pcru();
            }
        }
        processCarReviewUrl( 0, function() {
            ///step 6\\\
            var keysSorted = Object.keys(carsOwnerReview).sort(function(a,b){return carsOwnerReview[a]-carsOwnerReview[b]});
            var keysSortedReversed = keysSorted.reverse();
        });
    });
});

因為事情甚至可能變得更加復雜,所以我強烈建議您對本文進行研究。 確實值得一讀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM