通过URLS的承诺

时间:2015-06-03 20:45:40

标签: javascript web-scraping promise

我正试图找出一种处理动态数量的URL的方法。我们的想法是暂时运行,直到我们达到我们正在搜索的任何限制为止 - 比如说URLs。

    return new Promise(function(resolve, reject) {
        var links = [];
        var uri = feed.uri;
        var promise;
        var loadMore = true;
        var waiting = false;
        var page;
        while(loadMore) {
            if(!waiting) {
                waiting = true;
                promise = getListings(uri, feed, limit);
                promise.then(function(result) {
                    for (var i = 0; i < result.length; i++) {
                        if(links.length < limit) {
                            links.push(result[i]);
                        }
                    }
                    if(links.length < limit) {
                        // Load Pagination
                        uri = paginator.process(uri, feed, opts);
                        waiting = false;
                    } else {
                        resolve(links);
                        loadMore = false;
                    }
                }); 
            } 
        }
});

这是我目前所拥有的,但它运行不正常。我需要做的是浏览原始URL,然后继续浏览下一页,将URL添加到链接列表中。您可以假设paginator工作并返回该特定网站的下一个URL(例如www.google.com/page2)getListings正常工作并返回一系列链接。

我如何能够链接这些承诺,以便它可以遍历任意数量的页面(如果存在),并返回它找到的完整链接数组?

当在promise.then()内达到限制时,我似乎无法将loadMore变量更改为false。我希望它能够通过第一个URL,然后是下一个URL,直到达到限制。

我很感激有关如何将它们整合在一起的任何资源或想法。

2 个答案:

答案 0 :(得分:2)

使用您的承诺递归而不是循环。像这样:

var links = [];
function fetchNext(result) {
    for (var i = 0; i < result.length; i++) {
        if(links.length < limit) {
              links.push(result[i]);
        }
    }

    if (links.length < limit) {
        // Load Pagination
        uri = paginator.process(uri, feed, opts);

        // Recursion
        return getListings(uri, feed, limit).then(fetchNext);
    }
    else {
         return Q.fulfill(links); // Return resolved promise
    }
}

// Start recursion
var promise = fetchNext([]);
// or var promise = getListings(uri, feed limit).then(fetchNext);

答案 1 :(得分:0)

假设:

  • getListings()是异步的
  • paginator.process()同步
  • 名为getLinksAsync
  • 的函数包装器
  • 使用catch()方法实现承诺。

然后整个事情可以递归执行(没有任何丑陋的标志和错误恢复),如下所示:

function getLinksAsync() {
    function get(links, uri) { //like the outer function, get() returns a promise of links  
        return getListings(uri, feed, limit).then(function(result) {
            if(result && result.length) { //safety, in case getListings() gives a null or empty array
                links = links.concat(result).slice(0, limit);
                if(links.length < limit) {
                    return get(links, paginator.process(uri, feed, opts)); //recurse
                } else {
                    return links; //desired terminal condition - resolve the entire recursion with `links`.
                } 
            } else {
                return links; //resolve the entire recursion with links already discovered
            }
        }).catch(function(err) { //unpredicted error
            console.error(err);
            return links; // recovery - return any links already discovered before the error occurred.
        }); 
    }
    return get([], feed.uri);//seed the recursion with an empty array and feed.uri
}

如果if(result)安全性不够安全,您可以考虑使用try / catch结构

用法:

getLinksAsync().then(function(links) {
    //`links` array is available for use
    //its length may be anything from zero to `limit`
});