Promise.map() 进度指示器

Posted

技术标签:

【中文标题】Promise.map() 进度指示器【英文标题】:Promise.map() progress indicator 【发布时间】:2017-12-12 17:30:27 【问题描述】:

我正在尝试同时向 JSON API 发送许多 GET 请求。我在 Node.js 中使用 Bluebird Promise,并使用 request-promise 发送 HTTP 请求,如下所示:

const rp = require('request-promise');
//urlsArray is a 5000+ array of urls
Promise.map(urlsArray, url => 
  return rp(url)
    .then(results =>  
       return JSON.parse(results);
    ).catch(err =>  log(error););
).then(resultsArray => 
  log(resultsArray); // print out results
).catch(err => 
  log(error);
);

问题在于,如果数组中有 5000 多个 url,请求,即使是并发的,也可能需要很长时间,因为 map() 会等到所有请求都完成。在 map 处理请求时,如何将某种进度指示器(如百分比)打印到控制台?

我在每次请求后都尝试了log(results);,但这只是在控制台上打印了 5000 个东西,这不是很方便。我更喜欢一个百分比,或者一个显示大约完成了多少的数字。

【问题讨论】:

增加一个计数器并与已知数组长度进行比较 【参考方案1】:

请记住,承诺链就是:链。因此,您可以将then 插入到链中,为每个承诺进行控制台更新,并让它返回它收到的相同值。

实际上,查看您的代码,您甚至不必这样做,因为您已经在使用每个 URL 的 then 处理程序来解析 JSON。只需添加:

const rp = require('request-promise');
//urlsArray is a 5000+ array of urls
let completed = 0;                                 // ***
Promise.map(urlsArray, url => 
  return rp(url)
    .then(results =>  
       const parsed = JSON.parse(results);
       ++completed;                                // ***
       console.log(`Completed: $completed`);     // ***
       return parsed;
    ).catch(err =>  log(error););
).then(resultsArray => 
  log(resultsArray); // print out results
).catch(err => 
  log(error);
);

(请注意,我在说请求完成之前解析 JSON,以防 JSON 无效并抛出。)

但是,如果您还没有按照承诺进行活动,则可以轻松插入 then 处理程序。这是一个这样做的例子(使用原生承诺,但它与 Bluebird 相同):

const data = [1, 2, 3, 4, 5];

function withoutReportingProgress() 
    return Promise.all(
        data.map(value => new Promise(resolve => 
            setTimeout(_ => 
                resolve(value);
            , Math.random() * 500);
        ))
    );


function withReportingProgress() 
    let completed = 0;                              // ***
    return Promise.all(
        data.map(value => new Promise(resolve => 
            setTimeout(_ => 
                resolve(value);
            , Math.random() * 500);
        )
        .then(value =>                             // ***
            ++completed;                            // ***
            console.log(`Completed: $completed`); // ***
            return value;                           // ***
        ))                                         // ***
    );


console.log("Starting without...");
withoutReportingProgress()
    .then(_ => 
        console.log("Done without");
        console.log("Starting with");
        withReportingProgress()
            .then(_ => 
                console.log("Done with");
            );
    );
.as-console-wrapper 
  max-height: 100% !important;

【讨论】:

以上是关于Promise.map() 进度指示器的主要内容,如果未能解决你的问题,请参考以下文章

Flutter控件——常用控件:进度指示器

Flutter控件——常用控件:进度指示器

纱线进度指示器代表啥?

iOS进度指示器——NSProgress

进度指示器的状态没有变化[重复]

上传进度指示器以获取?