Проверка выполнения только одного из обещаний Jquery - PullRequest
2 голосов
/ 04 мая 2020

Promise.all возвращает одно Обещание, которое выполняется, когда все обещания, переданные как итеративные, выполнены. Имея это в виду, как можно проверить, выполнено ли только одно из обещаний? У меня есть фрагмент кода, показанный ниже:

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, «экспериментально и не полностью поддерживается всеми браузерами».

Кстати, вот моя функция getPi c:

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();
                });
        })
    }

Ответы [ 3 ]

1 голос
/ 04 мая 2020

Если вы поддерживаете современные браузеры, то вы можете использовать метод Promise.race(), возвращающий обещание, которое выполняет или отклоняет, как только одно из обещаний в итерируемом выполняет или отклоняет, со значением или причина этого обещания.

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

Вот диаграмма Совместимость браузера . Он не поддерживается только в IE.


Чтобы искать выполненное обещание, вы используете эту oneSuccess() вспомогательную функцию, например:

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))
0 голосов
/ 04 мая 2020

Вы можете создать собственную упрощенную версию Promise.any()

function promiseAny(promises) {
  let resolved = false,
      rejected = 0;

  return new Promise((resolve, reject) => {
    promises.forEach(p => {
      p.then(() => {
          if (!resolved) {
            resolved = true;
            resolve(p);
          }
        })
        .catch(() => {
          if (++rejected === promises.length) {
            reject("none of them fulfilled...");
          }
        });
    });
  });
}

// one of them fulfills
const p1 = new Promise(function(resolve) { setTimeout(() => resolve('one'), 500); });
const p2 = new Promise(function(resolve) { setTimeout(() => resolve('two'), 100); });

promiseAny([p1, p2]).then(x => console.log(x))
                  .catch(e => console.log(e));
                  
                  
// none of them fulfills
const p3 = new Promise(function(_, reject) { setTimeout(() => reject('three'), 500); });
const p4 = new Promise(function(_, reject) { setTimeout(() => reject('four'), 100); });

promiseAny([p3, p4]).then(x => console.log(x))
                  .catch(e => console.log(e));
0 голосов
/ 04 мая 2020

вы можете использовать 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
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...