Как использовать обещания в тестах Postman?

Мне нужно использовать асинхронный код в моем тесте Postman.

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

let promiseNumber = 0;

function resolvedPromise() {
    return new Promise((resolve, reject) => {
        pm.sendRequest('https://postman-echo.com/get', (err, res) => {
            if (err) {
                console.info(err);
                reject();
            } else {
                console.info(`Resolved promise ${++promiseNumber}`);
                resolve();
            }
        });
    });
}

resolvedPromise()
    .then(resolvedPromise)
    .then(resolvedPromise)
    .catch(err => console.info(err));

Ожидаемый результат на консоли будет:

Resolved promise 1
Resolved promise 2
Resolved promise 3

Но вместо этого я получаю:

Resolved promise 1

Есть ли способ сделать Promises или асинхронный код доступными в Postman?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
7
0
4 790
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

ОБНОВИТЬ: исходное решение использовало 2147483647 в качестве значения тайм-аута, теперь оно было переработано для использования Number.MAX_SAFE_INTEGER, как предложено в комментариях.

Я сделал еще несколько тестов и понял, что он всегда перестает работать после того, как я использую pm.sendRequest. Если я попытаюсь выполнить обещание, оно сработает.

Кажется, это известная ошибка при просмотре эта ветка.

Обходным путем будет только оставить открытый тайм-аут при обработке кода. Просто убедитесь, что все возможные пути очищают таймаут, иначе звонок будет зависать на 300000 лет ?

// This timeout ensure that postman will not close the connection before completing async tasks.
//  - it must be cleared once all tasks are completed or it will hang
const interval = setTimeout(() => {}, Number.MAX_SAFE_INTEGER);

let promiseNumber = 0;

function resolvedPromise() {
    return new Promise((resolve, reject) => {
        pm.sendRequest('https://postman-echo.com/get', (err, res) => {
            if (err) {
                console.info(err);
                reject();
            } else {
                console.info(`Resolved promise ${++promiseNumber}`);
                resolve();
            }
        });
    });
}

resolvedPromise()
    .then(resolvedPromise)
    .then(resolvedPromise)
    .then(() => clearTimeout(interval))
    .catch(err => {
        console.info(err);
        clearTimeout(interval);
    });

Теперь он печатает ожидаемый результат:

Resolved promise 1
Resolved promise 2
Resolved promise 3

Лично я буду использовать Number.MAX_SAFE_INTEGER вместо жестко запрограммированного 2147483647. Это не тот номер, но это максимальное безопасное целое число.

Elie G. 17.07.2019 20:02

Я попытался использовать его с Number.MAX_SAFE_INTEGER, и это не сработало. Если вы замените его чем-то более 1000, он работает.

seemcat 10.10.2020 01:51

Кажется, что каждый запрос занимает от 200 до 500 мс. Так что да, я могу подтвердить предыдущий комментарий, предполагающий что-нибудь более 1000. Чем больше запросов вы связываете, тем более высокая ценность вам понадобится для clearTimeout. Я также поиграл с верхним пределом и обнаружил, что 1 миллиард работает, но не 10 миллиардов (мс).

Henke 17.05.2021 13:06

@seemcat Согласитесь, это очень важно! НЕ используйте Number.MAX_SAFE_INTEGER !! Используйте что-нибудь вроде 100000.

blackr1234 02.08.2021 05:57

В дополнение к ответу Фелипе я хотел бы немного больше поделиться своим опытом использования Postman.

Поскольку мне нужно извлечь некоторые значения из ответов pm.sendRequest и использовать их при выполнении основного вызова (например, строки запроса) и / или в разделе Тесты, я запускаю сценарий в разделе Скрипт предварительного запроса и устанавливаю значения в переменных среды Postman.

Один важный момент, который я обнаружил, заключается в том, что я должен поместить весь код установки переменных (например, pm.environment.set(k, v)) перед clearTimeout(timeout). В противном случае, если я сделаю наоборот, код pm.environment.set(k, v) все равно будет запущен, но значение переменной окружения не будет обновлено.


Ниже приведен пример с Postman v8.5.1.

Главный вызов

Ожидайте получить TEST из переменных окружения.

GET http://google.com/{{TEST}}

Скрипт предварительного запроса

Ожидайте установки переменной среды TEST, значение которой берется из результатов нескольких API. В этом примере я просто использую последнее значение, возвращенное из Promise.all.

// make sure you do NOT use Number.MAX_SAFE_INTEGER !!
const timeout = setTimeout(() => {}, 100000);

const promise = () => {
    return new Promise((resolve, reject) => {
        console.info('Calling');
        pm.sendRequest('https://jsonplaceholder.typicode.com/todos/' + _.random(1, 100), (err, res) => {
            console.info('run');
            if (err) {
                reject();
            } else {
                resolve(res.json());
            }
        });
    });
}

Promise.all([
    promise(),
    promise(),
    promise(),
    promise(),
    promise(),
    promise(),
    promise(),
    promise(),
]).then(values => {
    console.info('All done');
    const exampleValue = values[values.length-1].id;
    console.info("Last ID: " + exampleValue);

    clearTimeout(timeout);

    // move this line before clearTimeout to fix TEST being undefined
    pm.environment.set("TEST", exampleValue);
});

Тесты

Ожидайте печати переменной среды TEST.

// you get undefined if pm.environment.set is run after clearTimeout
// you get correct value if pm.environment.set is run before clearTimeout
console.info(pm.variables.get("TEST"));

Как проверить

После копирования URL-адреса и всех скриптов в Postman откройте Консоль и щелкните Отправлять. Взгляните на строку запроса фактического вызываемого URL (например, GET http://google.com/%7B%7BTEST%7D%7D). Затем измените код, как указано в комментариях, и снова нажмите Отправлять. На этот раз все должно работать как положено.

Привет! Я только что попал в сценарий, подобный этому. Пытался реализовать это решение, и хотя оно работает при запуске из Postman, этого не происходит, когда я выполняю тесты с помощью newman. Моя переменная (устанавливающая ее как глобальную, коллекцию, среду или просто переменную) не устанавливается ... Есть идеи, может ли это иметь какое-то отношение к версии Postman? У меня 9.0.3 (последняя)

jprealini 24.09.2021 18:51

Другие вопросы по теме