Могу ли я отменить выполнение обещания? Пытается проверить тысячи ссылок и не хочет ждать истечения времени ожидания запросов - PullRequest
1 голос
/ 26 января 2020

Отказ от ответственности: у меня нет опыта в программировании или в сетях в целом, поэтому я могу упустить что-то совершенно очевидное.

Так что я делаю функцию в node.js, которая должна go над массив ссылок на изображения из моей базы данных и проверьте, работают ли они до сих пор. Нужно проверить тысячи ссылок, поэтому я не могу просто отключить несколько тысяч вызовов одновременно и ждать результатов, вместо этого я разбиваю запросы 10: 10 и выполняю головные запросы, чтобы минимизировать использование полосы пропускания.

У меня есть две проблемы.

Первый - это то, что после быстрой загрузки первых 10-20 ссылок другие запросы занимают немного больше времени, и у 9 или 10 из 10 из них истечет время ожидания. Это может быть связано с каким-то сетевым механизмом, который душит мои запросы, когда многие запускаются одновременно, но я думаю, что это, вероятно, связано с моей второй проблемой.

Вторая проблема заключается в том, что процесс проверки замедляется после нескольких итераций. Вот схема того, что я делаю. Я беру строковый массив ссылок на изображения и нарезаю его 10 на 10, а затем проверяю эти 10 сообщений в 10 обещаниях: (игнорируем переменные i и j, они там просто для отслеживания отдельных обещаний и тайм-аутов для регистрации / отладки )

const partialResult = await Promise.all(postsToCheck.map(async (post, j) => await this.checkPostForBrokenLink(post, i + j)));

в пределах checkPostForBrokenLink У меня есть гонка между выборкой и тайм-аутом в 10 секунд, потому что я не хочу ждать истечения времени ожидания соединения каждый раз, когда тайм-аут является проблемой, я дайте ему 10 секунд, а затем отметьте его как истекший тайм-аут и продолжайте.

const timeoutPromise = index => {
    let timeoutRef;
    const promise = new Promise<null>((resolve, reject) => {
        const start = new Date().getTime();
        console.log('===TIMEOUT INIT===' + index);
        timeoutRef = setTimeout(() => {
            const end = new Date().getTime();
            console.log('===TIMEOUT FIRE===' + index, end - start);
            resolve(null);
        }, 10 * 1000);
    });
    return { timeoutRef, promise, index };
};
const fetchAndCancelTimeout = timeout => {
    return fetch(post.fileUrl, { method: 'HEAD' })
        .then(result => {
            return result;
        })
        .finally(() => {
            console.log('===CLEAR===' + index); //index is from the parent function
            clearTimeout(timeout);
        });
};
const timeout = timeoutPromise(index);
const videoTest = await Promise.race([fetchAndCancelTimeout(timeout.timeoutRef), timeout.promise]);

если fetchAndCancelTimeout завершится раньше, чем timeout.promise, он отменит этот тайм-аут, но если тайм-аут заканчивается первым, обещание все еще остается. "разрешение" в фоновом режиме, несмотря на то, что код перешел. Я предполагаю, что именно поэтому мой код замедляется. Более поздние тайм-ауты занимают от 20 до 30 секунд от установки до запуска, несмотря на то, что установлены на 10 секунд Насколько я знаю, это должно быть из-за того, что основной процесс занят и у него нет времени для выполнения очереди событий, хотя я действительно не знаю, что он может делать, за исключением ожидания разрешения обещаний.

Итак, вопрос в том, во-первых, я делаю что-то глупое, чего я не должен делать, и это заставляет все быть медленными? Во-вторых, если нет, могу ли я как-нибудь вручную остановить выполнение обещания выборки, если время ожидания истекло, чтобы не тратить ресурсы на бессмысленный процесс? Наконец, есть ли лучший способ проверить, действительно ли большое количество ссылок, что я здесь делаю?

Ответы [ 2 ]

0 голосов
/ 07 февраля 2020

Здесь вы можете захотеть изучить библиотеку Bluebird Promise. В частности, я полагаю, что есть две функции, которые могут упростить вашу реализацию в отношении ограничения скорости ваших запросов и обработки таймаутов.

Bluebird Promise.map имеет параметр параллелизма ( link ), который позволяет вам Устанавливает количество одновременных запросов, а также имеет функцию Promise.timeout ( ссылка ), которая будет возвращать отклонение обещания, если произошло определенное время ожидания.

0 голосов
/ 27 января 2020

Я обнаружил проблему, и она, по крайней мере, не была напрямую связана с созданием обещаний Показанный код предназначен для проверки ссылок на видео, но для изображений вызов выборки выполнялся плагином, и этот плагин вызывал замедление. Когда я начал использовать один и тот же код для видео и изображений, процесс внезапно стал на порядок быстрее. Сначала я не думал проверять плагин, потому что он должен был только выполнить запрос головы и отформатировать результаты, которые не должны вызывать проблем.

Для тех, кто смотрит на это, пытается найти способ отмените выборку, @some предоставил идею, которая, кажется, может работать. Проверьте https://www.npmjs.com/package/node-fetch#request -отмена с абортным сигналом

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...