【问题标题】:Checking if only one of the Jquery Promises is fulfilled检查是否只有一个 Jquery Promises 被实现
【发布时间】:2020-05-04 13:28:52
【问题描述】:

Promise.all 返回一个 Promise,当所有作为迭代传递的 Promise 都已实现时,该 Promise 就会实现。考虑到这一点,如何检查是否只有一个承诺得到履行?我有一段代码如下所示:

Promise.all([getPic('blah.jpg'), getPic('blah_two.jpg')]).then(
                function(result) {
                    $('#div').hide();
                }
            ).catch(function(result) {
                $('#div').show();
            })

在这里,我想等待加载任何图像,即 blah.jpg 和 blah_two.jpg。如果其中任何一个被加载,则 $('#div').hide();。但是,我的代码会检查要加载的两个图像,这不是我真正想到的。您能否帮我解决这个问题,并在加载任何图像时隐藏$('#div')

我认为有一个Promise.any 可以满足我的想法;然而,正如 Mozilla 所说,“这是实验性的,并非所有浏览器都完全支持。”

顺便说一下,下面是我的getPic函数:

function getPic(src, div) {
        return new Promise(function(resolve, reject) {
            $(div).attr('src', src).on("error", function(e) {
                reject( "Cannot access " + src );
            })
                .on("load", function(e) {
                    resolve();
                });
        })
    }

【问题讨论】:

  • Promise.race()(履行或拒绝)或Promise.any()(仅履行)
  • @Andreas,Promise.any() 尚不支持所有浏览器,仍处于试验阶段,但如果能得到完全支持就好了。
  • 亲爱的@palaѕн。这个 raceToSuccess 函数是我想到的。然而,我无法在我的代码上实现它。请你帮帮我。

标签: jquery


【解决方案1】:

如果您支持现代浏览器,那么您可以使用Promise.race() 方法,在可迭代的promise 中的一个promise 满足或拒绝时返回一个promise,该promise 具有该promise 的值或原因。

Promise.race([getPic('blah.jpg'), getPic('blah_two.jpg')])
  .then(function(result) {
    $('#div').hide();
  }).catch(function(result) {
    $('#div').show();
  })

这是Browser compatibility 图表。仅在 IE 中不支持。


只有你使用thisoneSuccess()帮助函数来寻找履行的承诺:

function oneSuccess(promises){
  return Promise.all(promises.map(p => {
    // If a request fails, count that as a resolution so it will keep
    // waiting for other possible successes. If a request succeeds,
    // treat it as a rejection so Promise.all immediately bails out.
    return p.then(
      val => Promise.reject(val),
      err => Promise.resolve(err)
    );
  })).then(
    // If '.all' resolved, we've just got an array of errors.
    errors => Promise.reject(errors),
    // If '.all' rejected, we've got the result we wanted.
    val => Promise.resolve(val)
  );
}

然后传递getPic 图像数组,例如:

oneSuccess([getPic('blah.jpg'), getPic('blah_two.jpg')])
  .then(function(result) {
    $('#div').hide();
  }).catch(function(result) {
    $('#div').show();
  })

演示:

function oneSuccess(promises) {
  return Promise.all(promises.map(p => {
    return p.then(
      val => Promise.reject(val),
      err => Promise.resolve(err)
    );
  })).then(
    errors => Promise.reject(errors),
    val => Promise.resolve(val)
  );
}

// Case 1: First resolved promise
oneSuccess([
  Promise.resolve(1), Promise.reject(2), Promise.resolve(3)
]).then(result => console.log('First Success: ', result))

// Case 2: No resolved promise
oneSuccess([
  Promise.reject(1), Promise.reject(2), Promise.reject(3)
]).catch(error => console.log('All failed: ', error))

【讨论】:

  • @palaSH。 Promise.race 返回一个承诺,一旦可迭代中的一个承诺履行或拒绝,该承诺就会履行或拒绝。 Promise.race 的最后一部分不是我想要的。我希望其中一个承诺一定能兑现。
  • 我已经更新了有关如何实现该功能的代码。希望对您有所帮助!
  • 亲爱的@palaѕн。我将感谢您花时间帮助我。你胜了。谢谢一堆。但仍有一个问题。当两个图像都可用时,图像会立即加载,当只有一个可用时,显示 div 需要一秒钟。你能弄清楚问题是什么。如果是不可避免的,我会照现在的样子去。让我再谢谢你一次。 :x
  • 很抱歉,我无法在这里弄清楚这个具体问题。
【解决方案2】:

您可以使用Promise.race(),这是文档中的一个示例:

var p1 = new Promise(function(resolve, reject) { 
    setTimeout(() => resolve('one'), 500); 
});
var p2 = new Promise(function(resolve, reject) { 
    setTimeout(() => resolve('two'), 100); 
});

Promise.race([p1, p2])
.then(function(value) {
  console.log(value); // "two"
  // Both fulfill, but p2 is faster
});

【讨论】:

  • “我希望两个承诺中的一个绝对实现。” - Promise.race() 无法保证这一点
  • 关于 Promise.race,我同意@Andreas。
  • @H.M..,那么如果你想的话,你可以使用promise-any-polyfill,可能对你有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-04
  • 1970-01-01
  • 2018-11-16
  • 1970-01-01
  • 2018-07-01
  • 2023-04-10
相关资源
最近更新 更多