【问题标题】:Sequentially execute a bunch of WinJS promises from an array从数组中顺序执行一堆 WinJS 承诺
【发布时间】:2015-02-15 09:21:00
【问题描述】:

我有一组要按顺序下载的 URL,一次 2 个 URL。

var urls = [url1,url2,url3,url4,url5];

循环应该使用一些异步函数下载所有 URL,2 个 URL 按它们在数组中出现的顺序。 基本的顺序循环是使用.reduce 完成的,其工作方式如下:

preloadPromise = urls.reduce(function(p, url) {
  return p.then(WinJS.Utilities.Scheduler.schedulePromiseBelowNormal).then(function() {
    return preloadOneAsync(url);
  }).then(null, function(error) {
    if (error.name !== "Canceled") {
      logger.error("Could not create preloaded " + url, error);
    }
  });
}, WinJS.Promise.as());

现在我想介绍2个网址同时并行下载。

所以它会下载:[url1,url2] 然后 [url3,url4] 最后是 [url5]

函数的结果也应该是每个下载承诺的结果,类似于WinJS.Promise.join 的工作方式。

【问题讨论】:

    标签: javascript asynchronous coffeescript promise winjs


    【解决方案1】:

    让我们抽象出将数组分解为元组的函数

    function chunkBy(array, n) {
        var chunks = [];
        for (var i=0; i<array.length; i+=n)
            chunks.push(array.slice(i, n));
        return chunks;
    }
    

    以及为每个项目执行工作的函数:

    function tryToLoad(url) {
        return WinJS.Utilities.Scheduler.schedulePromiseBelowNormal() // not sure
        .then(function() {  return preloadOneAsync(url); })
        .then(null, function(error) {
            if (error.name !== "Canceled") {
                logger.error("Could not create preloaded " + url, error);
            }
        });
    }
    

    一个并行处理多个项目的函数就是

    function loadAll(urls) {
        return WinJS.Promise.join(urls.map(tryToLoad));
    }
    

    所以我们现在可以在序列的生成中使用它:

    preloadPromise = chunkBy(urls, 2).reduce(function(p, urls) {
        return p.then(function(prevResults) {
            return loadAll(urls).then(function(results) {
                return prevResults.concat(results);
            });
        });
    }, WinJS.Promise.as([]));
    

    结果数组通过p 链传递,在每一步之后总是增长。

    【讨论】:

    • 谢谢,你似乎是 Promise 的家伙 :) 不过有一件事:我相信 WinJS.Promise.join 如果任何承诺失败,那么我不知道要重试哪些 URL几秒钟后。
    • 只有一个 those guys :-) 是的,如果数组中的任何一个 Promise 失败,join 就会失败,但这与这里无关 - tryToLoad 从不失败,因为它捕获了所有错误。不过,错误处理程序可能会返回一个指示哪个 URL 失败的对象。
    • 但是错误处理程序不能像return WinJS.Promise.wrapError(error)那样返回失败的承诺
    • 是的,它必须返回一个result(表示应该重复某些事情),而不是自己失败。目前它只返回undefined,效果很好,但信息量不是很大。
    • 如果tryToLoad 被取消,我将如何中断.reduce 调用并跳过数组中的剩余项目?
    猜你喜欢
    • 1970-01-01
    • 2019-03-08
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 2017-01-13
    相关资源
    最近更新 更多