JQuery异步承诺使用嵌套循环



我是Node.js和promise的新手(在这里,我使用的是Q.js)。我正试图从一个具有以下结构的网站上制作一个刮刀:

  • main_page:有一个类别列表,每个类别都有一个指向商店列表页面的链接
  • 商店列表页面:有一个商店列表,每个商店都有一个指向商店详细信息页面的链接
  • 商店详细信息页面:包含我正在查找的数据

我做了第一个没有承诺的工作方法,但结果代码非常难看。因此,我认为这是一个使用承诺的好例子。

我不能用这种方法工作。当第二个循环完成时,应用程序不会继续(它从不执行end()方法)。此外,我不知道如何连接第三个环。

我该怎么做?

function get(url) {
    var deferred = Q.defer();
    requestify.get(url).then(function(response) {
        deferred.resolve(cheerio.load(response.getBody()));
    });
    return deferred.promise;
}
function process_main_page($) {
    var promises = [];
    $('.categories a').each(function(i) {
        var deferred = Q.defer();
        var storesList = $('.store');
        get($(this).attr('href')).then(function($) {
            deferred.resolve(process_stores_list(storesList));
        });
        promises.push(deferred);
    });
    return Q.all(promises);
}
function process_stores_list(storesList) {
    var promises = [];
    storesList.each(function() {
        // Here I need to make another ajax call for each store detail page, which has the data that I need.
        promises.push(deferred);
    });
    return Q.all(promises);
}
function end(res) {
    var deferred = Q.defer();
    fs.writeFile('output.json', JSON.stringify(myGatheredData, null, 4), function(err) {
        deferred.resolve(function() {
            res.send('File successfully written! - Check your project directory for the output.json file');
        });
    });
    return deferred.promise;
}
app.get('/', function(req, res) {
    get(url).then(process_main_page).then(end);
});

正如@BenjaminGruenbaum已经评论的那样,您的代码中充斥着延迟的反模式。Q.defer()的唯一(或多或少)合法使用是用于fs.writeFile,但您忘记处理那里的错误。只承诺API比较容易。

我不能用这种方法工作。

整体结构看起来不错。然而,有些要点:

  • 您似乎从未从具有存储的页面中获取stores_list。您获取了该页面,但使用类别页面中的var storesList = $('.store');解析了promise
  • end方法确实获得了作为其参数传递的myGatheredDataQ.all连接的结果数组)。它没有对res响应对象的任何访问权限

当第二个循环完成时,应用程序不会继续(它从不执行end()方法)。此外,我不知道如何连接第三个环。

我认为这就是原因——您可能已经在为Q.all()数组构建延迟,但从未解决它们。这使得返回的promise"挂起"(保持挂起),并且从未调用end回调。

var write = Q.nbind(fs.writeFile, fs);
function get(url) {
    return requestify.get(url).then(function(response) {
        return cheerio.load(response.getBody()));
    });
}
function process_main_page($_main) {
    var promises = $_main('.categories a').map(function(i) {
        // var storesList = $_main('.store'); // not sure what this did
        return get($_main(this).attr('href')).then(process_storelist_page);
    }).toArray();
    return Q.all(promises);
}
function process_storelist_page($_stores) {
    return process_stores_list($_stores('a.store').map(function() {
        return $_stores(this).attr('href'); // whatever?
    }).toArray());
}
function process_stores_list(storesList) {
    var promises = $.map(storesList, function(store_url) {
        // Here make another ajax call for each store detail page
        return get(store_url).then(process_store_page););
    });
    return Q.all(promises);
}
function process_store_page($_store) { // which has the data that I need.
    return /* select some data from the page */;
}
function save_data(myGatheredData) {
    return write('output.json', JSON.stringify(myGatheredData, null, 4)).then(function() {
        return 'File successfully written! - Check your project directory for the output.json file';
        });
    });
}
app.get('/', function(req, res) {
    get(url).then(process_main_page).then(save_data).then(function end(result) {
        res.send(result);
    });
});

当然,您也可以用函数表达式嵌套所有内容,而不是我使用的函数声明。

相关内容

  • 没有找到相关文章

最新更新