Проверка машинописи, если тело обещания не вызывает `resol` - PullRequest
1 голос
/ 22 января 2020

Есть ли какая-либо опция конфигурации машинописи или какой-то обходной путь, чтобы проверить, нет ли resolve вызова в new Promise обратном вызове?

Предположим, у меня есть обещание

new Promise(async (resolve, reject) => {
    try {
        // do some stuff
        // but not calling resolve()
    } catch (e) {
        reject(e)
    }
})

Я хочу машинопись, чтобы предупредить меня, что я не позвонил resolve(). Возможно ли это?

Я знаю, что могу использовать noUnusedParameters, но есть пара ситуаций, когда мне все еще нужны неиспользуемые параметры (например, request внутри express.Hanlder, где я использую только response, et c.)

Ответы [ 2 ]

2 голосов
/ 22 января 2020

Нет, это невозможно. Знать, вызывает ли код определенную функцию (в данном случае resolve), так же сложно, как проблему остановки . Существует доказательство того, что не существует алгоритма, который всегда может это определить.

Для иллюстрации предположим, что алгоритм определения того, вызывает ли функция resolve, существует и доступен через функцию callsResolve(func). Поэтому callsResolve(func) вернет true, когда определит, что func вызовет resolve (без фактического запуска func), и false, когда определит, что func будет не вызывать resolve.

Теперь представьте себе это func:

function func() {
    if (!callsResolve(func)) resolve();
}

... теперь у нас есть парадокс: что бы ни возвращал этот вызов callsResolve, это было неправильно. Так, например, если реализация callsResolve будет имитировать выполнение func (синхронно) и определит, что после предопределенного тайм-аута она должна вернуть false, вышеприведенное является демонстрацией функция, которая вызывает resolve сразу после истечения этого времени ожидания.

1 голос
/ 22 января 2020

Самое близкое, что вы можете получить к проверке времени компиляции, - это использовать синтаксис asyn c / await.

Если вы не хотите использовать это, вы могли бы прервать свои обещания, хотя вы бы сделать это с каждым вашим обещанием после / когда вы его создаете.

Решение может выглядеть следующим образом:

export const resolveAfterDelay = (timeout: number) => new Promise((r) => setTimeout(r, timeout));

export const rejectAfterDelay = async (timeout: number) => {

    return new Promise((resolve, reject) => setTimeout(() => reject(`Promise timed out as resolve was not called within ${timeout}ms`), timeout));

};

export const timeoutPromise = <T>(timeout: number) => async (p: Promise<T>): Promise<T> => {
    return Promise.race([p, rejectAfterDelay(timeout)]);
};

const timeoutAfter1s = timeoutPromise(1e3);
const timeoutAfter10s = timeoutPromise(10e3);

timeoutAfter10s(resolveAfterDelay(3e3)).then(success => console.log("SUCCESS IS PRINTED")).catch(console.error); // works
timeoutAfter1s(resolveAfterDelay(3e3)).then(success => console.log("NEVER REACHED")).catch(console.error); // aborts

const neverResolvingPromise = new Promise(() => {
});

timeoutAfter1s(neverResolvingPromise).catch(console.error); // promise never resolves but it will be rejected by the timeout

В нем используется Promise.race. В основном, все, что сначала восстанавливает или отклоняет, будет возвращено. Мы хотим всегда отклонять Обещание, если оно не разрешается вовремя.

Вы всегда должны будете обернуть свое Обещание при создании, как

timeoutAfter10s(new Promise(...));

И вам придется адаптировать время ожидания согласно на ваш случай использования.

...