【问题标题】:gathering multiple promise results? (plain javascript)收集多个承诺结果? (纯JavaScript)
【发布时间】:2017-02-22 00:38:04
【问题描述】:

我是 Promises 的新手,并尝试先从本地存储加载大量结果,如果失败,则转而从服务器获取数据。我不想使用 jquery - 忽略我目前正在使用 $.getJSON :-/

function loader1() {
    return new Promise(function (resolve, reject) {
        localforage.getItem("data1").then(function (value) {
            if (value !== null) {
                resolve(value);
            } else {
                $.getJSON("/myapp/data1.json").then(function (data) {
                    if (data !== null) {
                        resolve(data);
                    }
                }).catch(function (err) {
                    reject(err);
                });
            }
        });
    });
}

这对于一个文件来说很好。那么我会

loader1().then(function(result) { 
    // we have a result
    doSomethingElse();
}).catch(function (err) {
    // problem
});

但我想对多个文件执行此操作,其中一些文件位于本地存储中,其中一些文件从远程源加载 json。我想加载所有内容,完成后,执行我的应用程序的下一步。

Promise.all 似乎是问题,但我看不到如何获取每个加载器的结果;我在想它会是这样的:

Promise
    .all([loader1, loader2, loader3])
    .then(function(result1,result2,result3)) {
        ...

但这不是它的工作原理......所以我尝试了

Promise
    .all([loader1, loader2, loader3])
    .then(function(result)) {
        // var result1 = result[0];
        // var result2 = result[1];
        // var result3 = result[1];

但第二个的结果是函数而不是返回值...

搜索许多网站表明,像 Q 和 bluebird 这样的承诺系统有一个 spread 方法,看起来像我想要的。我可以在普通的旧 javascript 中执行此操作(如何?)还是应该考虑使用 Q 或 RSVP 之类的库来代替?

【问题讨论】:

标签: javascript es6-promise


【解决方案1】:

但是第二个的结果不是返回的函数 价值观...

您没有从您构造的Promise 中解析任何值。您也不会从链中的后续.then 中返回任何值。 您需要为每个加载程序函数执行以下操作:

function loader1() {

    var data = localforage.getItem("data1");
    
    data.then(function (data) {

        if (data !== null) {
             return data;
        } else {
            data = $.getJSON("/myapp/data1.json")

            if (data !== null) {
                return data;
            } else {
                return Error;
        }

    data.catch(function (err) {
       return (err);
    }

这确保对函数 loader1() 的调用将返回已解析的 Promise 或被拒绝的 Promise。然后您可以使用 guest271314 建议的解决方案:

Promise
.all([loader1(), loader2(), loader3()])
.then(function(result) {
  // var result1 = result[0];
  // var result2 = result[1];
  // var result3 = result[1];
 })
 .catch(function (err) {
   // problem
 });

但是请注意Promise同步执行。这意味着它不会自动等待任何异步操作在Promise 内完成。您必须自己解决这个问题,只有在异步操作完成后才解决它(通常通过在传递给异步函数的回调中解决)。

【讨论】:

  • localforage.getItem 本身会兑现承诺。这句话不是在调用 localforage 时解决(它可能还没有解决)。也就是说,如果localforage 失败,则回退到通过 xhr/elsewhere 获取数据,然后如果所有失败都拒绝所有内容。
  • 我已经根据您local forage.getItem返回Promise的信息更新了我的答案。
  • 您还应该注意,即使.then 自动返回Promise,您仍然需要在传递给它的回调函数中返回一些内容——否则.then 将返回Promise值为undefined
  • 另请注意,从localforage.getItem 返回的Promise 将是已经是resolvedrejected 的一个,因此您应该使用.then 作为@987654343 对其进行操作@ by design 只能是 resolvedrejected 一次。
【解决方案2】:

调用函数

Promise
.all([loader1(), loader2(), loader3()])
.then(function(result) {
  // var result1 = result[0];
  // var result2 = result[1];
  // var result3 = result[1];
 })
 .catch(function (err) {
   // problem
 });

另见How to cache a downloaded javascript fle which is downloaded using script tag

【讨论】:

    【解决方案3】:

    你可以使用destructuring:

    Promise.all([loader1(), loader2(), loader3()])
    .then(function([result1, result2, result3]) {
      ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-12
      • 2021-02-18
      • 2016-12-23
      • 2018-02-28
      相关资源
      最近更新 更多