Javascript 为什么承诺仍在等待?

Javascript 为什么承诺仍在等待?,javascript,node.js,web-scraping,promise,Javascript,Node.js,Web Scraping,Promise,这是我重新构造代码以正确利用承诺的尝试。整个程序是一个基本的webscraper 这方面的挑战是确保lastStep可以访问每个页面的HTML和URL,因此我尝试在nextStep()中返回一个对象 我正在控制台上记录html,它被正确地返回,但是由于某些原因,承诺被记录为这样:Promise{}。为什么会发生这种情况?我如何修复它 谢谢大家! //Modules being used: var cheerio = require('cheerio'); var json2csv = requi

这是我重新构造代码以正确利用承诺的尝试。整个程序是一个基本的webscraper

这方面的挑战是确保lastStep可以访问每个页面的HTML和URL,因此我尝试在
nextStep()
中返回一个对象

我正在控制台上记录html,它被正确地返回,但是由于某些原因,承诺被记录为这样:
Promise{}
。为什么会发生这种情况?我如何修复它

谢谢大家!

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

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

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

var remainder;
var tshirtArray = [];


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 scrape (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 array of links
            return links;
        });
}


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

    for(var i = 0; i < arrayOfLinks.length; i++){
        promiseArray.push(requestPromise(arrayOfLinks[i]));
        var promises = Promise.all(promiseArray);
        console.log(promises);
    }

    return {arrayOfHtml: promises , arrayOfUrls: arrayOfLinks};                 
}


function lastStep (obj){ 
    for(var i = 0;  i < obj.arrayOfHtml.length; i++){
        var $ = cheerio.load(obj.arrayOfHtml[i]);

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

            //add page to set
            urlSet.add(obj.arrayOfUrls[i]);
            console.log(obj.arrayOfUrls[i]);

        } else if(remainder == undefined) {
            //if not a product page, add it to remainder so it another scrape can be performed.
            remainder = obj.arrayOfUrls[i];
            console.log("remainder: " + remainder);                         
        }
    }
}


scrape(url)
    .then(nextStep)
    .then(lastStep)
    .catch(function(err) {
        // handle any error from any request here
        console.log(err);
     });
//正在使用的模块:
var cheerio=需要('cheerio');
var json2csv=require('json2csv');
var请求=要求(“请求”);
var力矩=要求的(‘力矩’);
var fs=需要('fs');
//加密url
var url='1〕http://shirts4mike.com/';
//tshirt页面的url
var urlSet=new Set();
var余数;
var tshirtaray=[];
const requestPromise=函数(url){
返回新承诺(功能(解决、拒绝){
请求(url、函数(错误、响应、html){
如果(错误)返回拒绝(错误);
如果(!error&&response.statusCode==200){
返回解析(html);
}       
});
});
}
函数刮取(url){
返回请求承诺(url)
.then(函数(html){
var$=cheerio.load(html);
var-links=[];
//获取所有链接
$('a[href*=shirt]')。每个(函数(){
var a=$(this.attr('href');
//添加到链接数组中
links.push(url+a);
});
//返回链接数组
返回链接;
});
}
函数下一步(arrayOfLinks){
var promiseArray=[];
对于(变量i=0;i
您可以尝试几件事。首先,在
requestPromise
函数中,调用'resolve()'和
reject()
时不需要返回。我不知道这是否会有什么不同,但你至少可以试试

接下来,正如评论中所讨论的,您应该更改拒绝和解决请求承诺的方式。最简单的是:

if(error) {
    reject(error);
} else {
    resolve(html);
}
假设没有错误(只有4xx或5xx状态代码才会发生错误),但状态代码不是200?您可以获得2xx或3xx范围内的任何内容,但不会得到错误,在这种情况下,
requestPromise
将永远不会得到解决或拒绝。这肯定会给你带来麻烦,因为所有的承诺都必须以这样或那样的方式结束

下一个问题在
nextStep
中。我将重构如下:

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

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

    return Promise.all(promiseArray)
          .then(function (arrayOfHtml) {
            return {arrayOfHtml: promises , arrayOfUrls: arrayOfLinks};
          });                
} 
函数下一步(arrayOfLinks){
var promiseArray=[];
对于(变量i=0;i
使用
Promise.all
,您希望首先填充承诺数组,然后在完成所有异步调用后,即调用
Promise.all(promisesArray)
all
末尾的额外
then
将获取来自承诺数组的html,然后将其作为承诺与
arrayOfLinks
一起返回到承诺链的下一步,在本例中,这是您的
lastStep

如果这些都不能解决您的问题,您将需要回顾状态代码问题,我以前遇到过状态代码为202的问题,这意味着请求已被接受,但请求的处理尚未完成。(您可以阅读有关HTTP状态代码的更多信息)。这是一个非常相似的情况,我们有一堆的网址,我们提出请求。我们最终将所有得到202的URL放回到
tryAgain
数组中,然后再次尝试点击它们

在您的情况下,您有一个解决方案,可以通过两种方法来解决它。最简单的做法是拒绝承诺所有状态代码,但200除外,这有点严格。您可以做的另一件事是,如果没有错误并且状态代码不是200,那么您可以使用一些特殊值来解析承诺,或者简单地使用非200状态代码,这将表明您需要重试。然后在
nextStep
之后,您可以过滤所有使用非200代码解析的结果,然后再次尝试点击它们。之后,您可以完成
lastStep
。如果你试过其他所有方法,但都不管用,我会尝试这些方法中的一种。不过这需要一些努力


希望这有帮助。如果您有任何问题,请告诉我。

您的代码中有一个未处理的
else

if(error) return reject(error);

if(!error && response.statusCode == 200){
    return resolve(html);   
}
让我们重新安排一下,以便更清楚。由于返回
,上述代码与此完全相同:

if(error) {
    reject(error);
}
else if (response.statusCode == 200) {
    resolve(html);   
}
else {
    // keep this promise pending FOREVER!!
}
你还没有处理好金融机构
if(error) return reject(error);

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

reject(new Error('Not code 200'));
if(error) return reject(error);

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

resolve(html);