Вы можете определить фабричную функцию для инкапсуляции вашего метода search()
с запрошенным поведением отмены.Обратите внимание, что хотя конструкторы Promise
обычно считаются антишаблоном , в этом случае необходимо сохранить ссылку на каждую функцию reject()
в наборе pending
, чтобы реализовать раннюю отмену.
function cancellable(fn) {
const pending = new Set();
return function() {
return new Promise(async (resolve, reject) => {
let settle;
let result;
try {
pending.add(reject);
settle = resolve;
result = await Promise.resolve(fn.apply(this, arguments));
} catch (error) {
settle = reject;
result = error;
}
// if this promise has not been cancelled
if (pending.has(reject)) {
// cancel the pending promises from calls made before this
for (const cancel of pending) {
pending.delete(cancel);
if (cancel !== reject) {
cancel();
} else {
break;
}
}
settle(result);
}
});
};
}
// internal API function
function searchImpl(timeout) {
return new Promise((resolve, reject) => {
setTimeout(resolve, timeout);
});
}
// pass your internal API function to cancellable()
// and use the return value as the external API function
const search = cancellable(searchImpl);
search(200).then(() => {
console.log('search1 resolved');
}, () => {
console.log('search1 rejected');
});
search(2000).then(() => {
console.log('search2 resolved');
}, () => {
console.log('search2 rejected');
});
search(1000).then(() => {
console.log('search3 resolved');
}, () => {
console.log('search3 rejected');
});
search(500).then(function() {
console.log('search4 resolved');
}, () => {
console.log('search4 rejected');
});
Эта фабричная функция использует итерацию порядка вставки Set
, чтобы отменить только ожидающие обещания, возвращаемые вызовами, выполненными до вызова, возвращающего обещаниеэто только что завершилось.
Обратите внимание, что отмена обещания с использованием reject()
не завершает какой-либо базовый асинхронный процесс, инициированный созданием обещания.Каждый HTTP-запрос будет продолжен до завершения, как и любые другие внутренние обработчики, которые вызываются в search()
до выполнения обещания.
Все, что делает cancellation()
, вызывает переход внутреннего состояния возвращаемого обещания из в ожидании в отклонено вместо выполнено , если позднееОбещание устанавливается первым, так что соответствующий код будет вызываться соответствующим обработчиком для разрешения обещания.