首页 > 解决方案 > 在 Node.js 中请求信息时延迟承诺请求

问题描述

我正在使用gpapi库来查找 Play 商店并存储有关在 Play 商店中找到的应用程序的信息。我首先找到一个应用程序的相关应用程序(大约 20 个应用程序),然后我请求每个应用程序的详细信息。这是由库作为承诺请求完成的。我尝试在请求之间添加延迟,因为在当前状态下,所有请求同时执行,因此我收到 429 错误(请求过多),一段时间后,我暂时被 Google 服务器完全禁止。

function getRelatedApps(pkg) {
    api.login()
        .then(function () {
            api.related(pkg).then(function (res) {
                for (let key in res['0'].child) {
                    let appId = res['0'].child[key].docid;
                    if (!storedApps.has(appId)) {
                        relatedArray.add(appId);
                    }
                }

                Promise.map(relatedArray, function (appId) {
                    getInfo(appId);
                }, {concurrency: 1});
            });
        });
}

我尝试Promise.delay在每个请求之间添加并使用该setTimeout函数没有任何效果,因为请求仍然同时执行。

当使用带有setTimeout内部的 while 循环时,一般不会执行任何请求。

我怎么能在每次调用getInfo函数之间暂停?

标签: javascriptnode.jspromisegoogle-playrequest-promise

解决方案


如果您使用的是 Bluebird,那么您拥有Promise.map()并且Promise.delay()可以使用,您可以执行以下操作:

function getRelatedApps(pkg) {
    return api.login()
    .then(() => api.related(pkg))
    .then(res => {
        let relatedArray = Object.values(res['0'].child)
            .map(value => value.docid)
            .filter(appId => !storedApps.has(appId));
        return Promise.map(relatedArray, appId => Promise.delay(1000, getInfo(appId)), {concurrency: 1});
    });
}

否则,您可以使用自制delay()函数和Array.prototype.reduce()模式实现相同的效果,如下所示:

function delay(ms, val) {
    return new Promise(resolve => {
        setTimeout(() => { resolve(val); }, ms);
    });
}
function getRelatedApps(pkg) {
    return api.login()
    .then(() => api.related(pkg))
    .then(res => {
        return Object.values(res['0'].child)
        .map(val => val.docid)
        .filter(appId => !storedApps.has(appId));
        .reduce((p, appId) => p.then(() => delay(1000, appId)).then(getInfo), Promise.resolve());
    });
}

笔记:

  1. Object.values()可从 Node.js 7.0.0 获得。对于较早版本的 Node,请恢复为relatedArray问题中的构建。
  2. 假设问题relatedArray最初是空的。
  3. 根据需要调整 1000 ms 延迟。

推荐阅读