【问题标题】:Continue after array of promises has completed either with success or fail在一系列承诺成功或失败完成后继续
【发布时间】:2018-07-07 08:19:15
【问题描述】:

我想在所有承诺都解决或拒绝时继续,并在最后显示字符串“##### should be final call ####”。


TL;DR;

我忘记在 map 函数中返回 promise。


我正在尝试使用这种方法: Wait until all ES6 promises complete, even rejected promises

下面的代码有什么问题?

我希望 Promise.all().then 处理程序最终会被调用,毕竟其他的。

结果变量包含一个未定义值的数组。

console.clear();

$(document).ready(function () {

    var url = "https://httpbin.org/get?";
    a = [];

    a.push(new Promise(function (resolve, reject) {
        $.get(url + Math.random()).then((res) => resolve()).fail(() => {
            reject();
        });
    }));
    a.push(new Promise(function (resolve, reject) {
        $.get(url + Math.random()).then((res) => resolve()).fail(() => {
            reject();
        });
    }));

    var mr = getPromise();

    function getPromise() {
        var promise = new Promise(function (resolve, reject) {
            window.setTimeout(function () {
                reject();

            }, 1000);
        });
        return promise;
    }

    a.push(mr);

    a.push(new Promise(function (resolve, reject) {
        $.get(url + Math.random()).then((res) => resolve()).fail(() => {
            reject();
        });
    }));

    a.push(new Promise(function (resolve, reject) {
        $.get(url + Math.random()).then((res) => resolve()).fail(() => {
            reject();
        });
    }));

    Promise.all(a.map((p) => {
            p.catch((e) => {
                console.log("failed promise catch");
            });
        }))
        .then((results) => {
            console.log("##### should be  final call  ####");
        })
        .catch((e) => {
            console.log("final catch block executed");
        });


}); // ready end
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

【问题讨论】:

  • 这在 NodeJS 中按预期工作。奇怪的是它在浏览器中失败了!

标签: javascript jquery promise es6-promise


【解决方案1】:

首先,避免Promise constructor antipattern!只需使用

function getPromise() {
  return new Promise(function(resolve, reject) {
    window.setTimeout(reject, 1000);
  });
}
const url = "https://httpbin.org/get?";
a = [
  Promise.resolve($.get(url+ Math.random())),
  Promise.resolve($.get(url+ Math.random())),
  getPromise(),
  Promise.resolve($.get(url+ Math.random())),
  Promise.resolve($.get(url+ Math.random()))
];

那么你的问题只是你忘记了return 来自map 回调的链式承诺(带有处理的拒绝),所以你在undefineds 的数组上调用了Promise.all,它立即实现了。将其更改为:

Promise.all(a.map(p => {
  return p.catch(e => { console.log("failed promise catch"); });
//^^^^^^
}))
.then(results => {
  console.log("##### should be  final call  ####");
}, e => {
  console.log("final catch block executed");
});

【讨论】:

  • 谢谢伯吉。但我还有一个关于Promise.resolve(..) 的问题。如果$.get 请求的.then 处理程序依赖于当前正在执行的函数上下文中的数据会怎样。在Promise.then(..) 我只得到请求的结果...
  • here 一个高度赞成的答案,它使用这种反模式来承诺原生 xhr 请求。实际上所有答案都使用这种反模式。
  • @Legends “当前正在执行的上下文”是什么意思? then 也没有什么不能做的。
  • @Legends 不,使用Promise 构造函数来承诺任何事情都不是反模式。尝试承诺已经返回承诺的事物(例如 $.ajaxfetch),或者编写自己的(但更糟糕的)then 模式是一种反模式。
  • 这也是我在此评论线程中关于使用Promise.resolve https://stackoverflow.com/a/22776850/2581562 时的其他上下文参数的第一个问题的答案
【解决方案2】:

您忘记将承诺返回到地图中。你承诺的 undefined 数组会立即解决。

console.clear();

$(document).ready(function(){

function getPromise() {
  return new Promise((resolve, reject) => window.setTimeout(reject, 1000));
}

function getRandomUrl() {
  return new Promise((resolve, reject) => $.get(url+ Math.random()).done(resolve).fail(reject));
}

var url= "https://httpbin.org/get?";
a = [];

a.push(getRandomUrl());
a.push(getRandomUrl());
a.push(getPromise());
a.push(getRandomUrl());
a.push(getRandomUrl());

Promise.all(a.map(p => {
    return p.catch(console.log);   
  }))
  .then((results) => {
    console.log("##### should be  final call  ####");
  })
  .catch((e) => {
    console.log("final catch block executed");
  });


});// ready end
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-21
    • 2018-04-25
    • 2017-09-07
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多