zkrvndm
@zkrvndm
Архитектор решений

Существует ли аналог Promise.allSettled для jQuery.Deferred?

Я в курсе про существование метода jQuery.when, но он ведет себя аналогично Promise.all, что несколько не то, ведь иногда нужно сначала дождаться выполнения всех промисов, а не только первого НЕ успешного. На чистом JavaScript для этого есть метод Promise.allSettled, а вот если я захочу сделать подобное на чистом ванильном jQuery, тогда как быть?
  • Вопрос задан
  • 194 просмотра
Решения вопроса 2
Alexandroppolus
@Alexandroppolus
кодир
Наверно, так же, как и для allSettled

function convert(deffered) {
    return deffered.then(
        data => ({status: 'fulfilled', value: data}),
        error => ({status: 'rejected', reason: error})
    );
}

jQuery.whenAllSettled = function(...args) {
    return jQuery.when(...args.map(convert));
};
Ответ написан
zkrvndm
@zkrvndm Автор вопроса
Архитектор решений
Я понял в чем был не прав. В случае с jQuery никаких аналогов Promise.allSettled не нужно никогда.

Для всех возможных случаев достаточно одного jQuery.when() - просто потому что в эту функцию мы всегда передаем Deferred, а передаваемый Deferred мы всегда можем подрихтовать при помощи jQuery.always() так, чтобы он завершался через deferred.resolve()

Допустим, нам надо сделать 3 запроса одновременно и получить все результаты, при этом нам не важно успешно завершились запросы или какие-то из них были завершены с ошибкой. Если использовать jQuery.when() в лоб, то разумеется мы не сможем получит все результаты, так как jQuery.when() завершится при получении первого неуспешного результата, проигнорировав все остальные запросы, но если передавать в него немного поправленный Deferred, то никаких проблем с обработкой всех результатов не предвидится:
// Ссылки:

var urls = [
	'/link1',
	'/',
	'/link3'
];

var deferreds = []; // Массив для записи Deferred

// Перебираем ссылки в цикле jQuery:

jQuery.each(urls, function(num, link) {
	
	// Создаем новый Deferred и
	// записываем его наш массив:
	deferreds.push(jQuery.Deferred());
	
	// Отправляем запрос, указав через
	// always, чтобы после завершения он
	// успешно завершил созданный ранее Deffered:
	jQuery.ajax(link).always(deferreds[num].resolve);
	
});


// Используем when, чтобы дождаться завершения всех Deferred:

jQuery.when.apply($, deferreds).done(function() {
	
	// После завершения всех Deferred выведем результаты запросов:
	
	console.log('Запросы успешно отправлены, их результаты ниже:');
	console.dir(arguments);
	
});

Очевидно, что вместо jQuery.ajax может использоваться любая другая функция возвращающая Deferred, т. е. этот принцип можно применять везде и для всего. Конечно промисы применять было бы в удобнее, чем объекты Deferred, но в защиту Deferred скажу, что он может все то же, что и промисы, включая возможность использовать async / await + у него есть некоторые фишки, которых нет у промисов.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы