使用promises收集未知大小的分页数据

时间:2015-11-13 12:09:54

标签: javascript node.js promise

我正在查询REST-API以获取所有组。这些小组分批进行50次。我希望在继续处理之前收集所有这些小组。

到目前为止,我依赖回调,但我想使用promises链接所有组的检索,然后进一步处理结果数组。

我只是不太了解如何使用promises替换递归函数调用。

我如何使用A + promises来逃避我使用此代码创建的回调地狱?

antlr-2.7.7.jar
gemfire-8.0.0.jar
jackson-annotations-2.6.0.jar
jackson-core-2.6.0.jar
jackson-databind-2.6.0.jar
json-simple-1.1.1.jar

3 个答案:

答案 0 :(得分:4)

使用标准承诺,包装所有现有代码,如下所示:

function addToGroups() {
    return new Promise(function(resolve, reject) {
        ...  // your code, mostly as above
    });
}

在您的代码中,当您完成后请致电resolve(data),或reject()如果由于某种原因,调用链失败。

为了使整个事情变得更加“承诺”和#34;,首先让一个函数collectGroups返回一个承诺:

function promiseGet(url) {
    return new Promise(function(resolve, reject) {
        sc.get(url, function(error, data) {
            if (error) {
                reject(error);
            } else {
                resolve(data);
            }
        });
    }
}
// NB: promisify-node can do the above for you

function collectGroups(offset, stride) {
    return promiseGet('/tracks/'+ CURRENT_TRACK_ID +'/groups?limit=' + stride + '&offset=' + offset , OAUTH_TOKEN);
}

然后在代码中使用此Promise:

function addToGroups() {
    var results = [], stride = 50;
    return new Promise(function(resolve, reject) {
        (function loop(offset) {
            collectGroups(offset, stride).then(function(data) {
                if (data.length) {
                    results.push(data);
                    loop(offset + stride);
                } else {
                    resolve(data);
                }
            }).catch(reject);
        )(0);
    });
}

答案 1 :(得分:1)

这可行。我正在使用https://github.com/kriskowal/q承诺。

SELECT COUNT(*) FROM `products`, `components`, `tradeNames` 
INNER JOIN `componentsMap` ON componentsMap.product_id = product.id 
INNER JOIN `components` ON componentsMap.component_id = components.id 
INNER JOIN `tradeNamesMap` ON .tradeNamesMap.product_id = products.id 
INNER JOIN `tradeNames` ON tradeNamesMap.tradeName_id = tradeNames.id 
WHERE (((((LOWER(inci) LIKE '%abies%') 
          OR (trade_name.LOWER(name) LIKE '%abies%')) 
         OR (components.LOWER(no_cas)='abies')) 
        OR (components.LOWER(no_einecs)='abies')) 
       OR (components.LOWER(name)='abies'))
AND (`published`=1) 
ORDER BY `trade_name`.`name` DESC

让我知道它是否有效。

答案 2 :(得分:1)

以下是完整示例,使用spex.sequence

var spex = require("spex")(Promise);

function source(index) {
    return new Promise(function (resolve) {
        sc.get('/tracks/' + CURRENT_TRACK_ID + '/groups?limit=50&offset=' + index * 50, OAUTH_TOKEN, function (error, data) {
            resolve(data.length ? data : undefined);
        });
    });
}

spex.sequence(source, {track: true})
    .then(function (data) {
        // data = all the pages returned by the sequence;
    });

我认为它不会比这更简单;)