简体   繁体   English

为什么这是未处理的承诺拒绝?

[英]Why is this an Unhandled Promise Rejection?

I'm trying to rewrite my code to utilize promises correctly. 我正在尝试重写我的代码以正确利用Promise。

The full program is supposed to scrape the data from a tshirt site. 完整的程序应该从T恤站点中抓取数据。 This first block of code is supposed to enter the front page of the site, grab the product pages that are immediately available and then store the URL's in an array. 该第一段代码应该进入网站的首页,获取立即可用的产品页面,然后将URL存储在数组中。 The remainder URL's will be stored in 'remainder' for a secondScrape to be performed later on. 剩余的URL将存储在“ remainder”中,以便稍后执行secondScrape。

Currently manually unit testing each section: 当前手动对每个部分进行单元测试:

//TASK: Create a command line application that goes to an ecommerce site to get the latest prices.
    //Save the scraped data in a spreadsheet (CSV format).



//Modules being used:
var cheerio = require('cheerio');
var request = require('request');

//harcoded url
var url = 'http://shirts4mike.com/';

//url for tshirt pages
var urlSet = new Set();

var remainder;

   const requestPromise = function(url) {
    return new Promise(function(resolve, reject) {
        request(url, function(error, response, html) {

            if(error) return reject(error);

            if(!error && response.statusCode == 200){
                return resolve(html);   
            }       
        });
    });
}


function firstScrape (url) {
    return requestPromise(url)
        .then(function(html) {
            var $ = cheerio.load(html);

            var links = [];

            //get all the links
            $('a[href*=shirt]').each(function(){
                var a = $(this).attr('href');

                //add into link array
                links.push(url + a);

            });
            return links;
            // return this array you've made
        });
}


function nextStep (arrayOfLinks) { 
    var promiseArray = [];

    for(var link in arrayOfLinks){
        promiseArray.push(requestPromise(link));
        return Promise.all(promiseArray);
    }                   
}


function lastStep (arrayOfHTMLresults){ 
    for(var html in arrayOfHTMLresults){
        var $ = cheerio.load(html);

        //if page has a submit it must be a product page
        if($('[type=submit]').length !== 0){

            //add page to set
            urlSet.add(scrapeLink);

        } else if(remainder == undefined) {
            //if not a product page, add it to remainder so it another scrape can be performed.
            remainder = scrapeLink;                         
        }
    }
    console.log(urlSet);
    console.log(remainder);
}


firstScrape(url)
    .then(nextStep)
    .then(lastStep);

I'm currently getting the following error: 我目前遇到以下错误:

(node:71094) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Error: Invalid URI "0"

This is the code I'm trying to promisify: 这是我要宣传的代码:

// Load front page of shirts4mike
function firstScrape(){
    request(url, function(error, response, html) {
        if(!error && response.statusCode == 200){
            var $ = cheerio.load(html);

        //iterate over links with 'shirt'
            $('a[href*=shirt]').each(function(){
                var a = $(this).attr('href');

                //create new link
                var scrapeLink = url + a;

                //for each new link, go in and find out if there is a submit button. 
                //If there, add it to the set
                request(scrapeLink, function(error,response, html){
                    if(!error && response.statusCode == 200) {
                        var $ = cheerio.load(html);

                        //if page has a submit it must be a product page
                        if($('[type=submit]').length !== 0){

                            //add page to set
                            urlSet.add(scrapeLink);

                        } else if(remainder == undefined) {
                            //if not a product page, add it to remainder so it another scrape can be performed.
                            remainder = scrapeLink;                         
                        }
                    }
                });
            });     
        }
    });
}

What I can't work out is how can I use urlSet.add(scrapeLink); urlSet.add(scrapeLink);是如何使用urlSet.add(scrapeLink); in lastStep() when it doesn't know what scrapeLink is? lastStep()何时不知道scrapeLink是什么?

Any idea why? 知道为什么吗? Thank you 谢谢

.add() is not an Array.prototype method, you also return promiseArray within for loop instead of pushing a Promise to promiseArray and using Promise.all() .add()不是Array.prototype方法,您还promiseArrayfor循环中return promiseArray for而不是将Promise推送到promiseArray并使用Promise.all()

function nextStep (arrayOfLinks) { 
    var promiseArray = [];

    for(var i = 0; i < arrayOfLinks.length; i++) {
        var link = requestPromise(arrayOfLinks[i]);
        promiseArray.push(link);
    }   

    return Promise.all(promiseArray)                
}

UPDATE due to question changing: 由于问题变化而导致的更新:

So from firstScrape() you could return a results Object instead of just an array of links: 因此,从firstScrape()您可以返回结果对象,而不仅仅是返回一组链接:

return { scrapeLink: link, result: links }

You would then get that in nextStep() as the result of the promise where you could return something with the same shape again: 然后,您将在nextStep()中得到该承诺的结果,在那里您可以再次返回具有相同形状的东西:

return { scrapeLink: firstStepResult.scrapLink, result: Promise.all(promiseArray) }

Then in lastStep() instead of arrayOfHTMLresults getting passed in you would then have an Object which would look like: 然后在lastStep()而不是通过arrayOfHTMLresults ,您将拥有一个类似于以下内容的对象:

{ scrapeLink: "http://someurl.com", result: arrayOfHTMLresults }

PREVIOUS answer: 上一个答案:

You will need to initialize your variable in the for...in loop. 您将需要在for ... in循环中初始化变量。 eg with const , var or let depending on your use case and JS version. 例如,使用constvarlet取决于您的用例和JS版本。

for(var link in arrayOfLinks){
    promiseArray.add(requestPromise(link));
    return promiseArray;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM