将ES6 Generator与Promise相结合

时间:2015-07-20 18:43:51

标签: ajax generator

让我们说我正在进行ajax调用。并且后端一次只返回10个项目。我可以使用' skip'参数,以获得更多元素。服务器还返回元素总数。因此,如果我想获得所有现有元素,我的工作流程应该如下:

  • 进行初始ajax调用
  • 如果totalRows大于(previousSkip(initialy 0)+ limit(常数10))则
    • 再次使用skip = previousSkip + 10
    • 进行调用

递归函数不会在这里工作,对吧?那么如何使用发电机来实现呢?

我希望只获得必要的数据,例如。如果我调用.next()5次,它会进行5次调用,并获得50行,即使数据库中有总计有数百万行。

1 个答案:

答案 0 :(得分:0)

对于使用promises的异步调用,你可以用生成器做的最多就是它返回promise。下面以jQuery ajax为例,您当然可以替换自己的promisified ajax方法。

function genGetData* (url, start, limit) {
    while (start < start+2000) { // conditional is just a safety net
        yield $.get(url, {start: start, limit: limit});
        start += limit;
    }
}

var getData = genGetData('foo.php', 0, 10);

// get first 30 rows
$.when(getData.next().value,getData.next().value,getData.next().value)
    .then(function () {
        var args = Array.prototype.slice.call(arguments);
        args.forEach(function (data) {
            console.log(data); // will be in order by set of results
        });
    });

将这种情况应用到您的情况中,您需要创建一个变量来保存总记录并将其传递给您的生成器,以便在第一次请求之后,您可以更新它以便生成器知道何时停止

function genGetData* (url, options) {
    while (options.start < options.total) {
        yield $.get(url, {start: options.start, limit: options.limit});
        options.start += options.limit;
    }
}

var options = {
    start: 0,
    limit: 10,
    total: 1 // this just needs to be greater than start, we'll update it in a moment
}
var getData = genGetData('foo.php', options);

getData.next().value.then(function (data) {
    options.total = data.total;
    var promiseArray = [];
    for (let promise of getData) {
        promiseArr.push(promise);
    }
    $.when.apply(null, promiseArray).done(function () {
        console.log(args); // data in order in chunks of 10, excluding the first 10
    });
});

因此,当第一次在生成器上调用.next()时,我们访问它的promise并等待它完成,以便我们可以得到总数。在我们更新总数之后,我们然后在生成器上执行for循环以获取其余数据。然而,这仍然无法解决您将并行发送太多请求的事实。