Мне нужно использовать асинхронный код в моем тесте 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?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


ОБНОВИТЬ: исходное решение использовало 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, и это не сработало. Если вы замените его чем-то более 1000, он работает.
Кажется, что каждый запрос занимает от 200 до 500 мс. Так что да, я могу подтвердить предыдущий комментарий, предполагающий что-нибудь более 1000. Чем больше запросов вы связываете, тем более высокая ценность вам понадобится для clearTimeout. Я также поиграл с верхним пределом и обнаружил, что 1 миллиард работает, но не 10 миллиардов (мс).
@seemcat Согласитесь, это очень важно! НЕ используйте Number.MAX_SAFE_INTEGER !! Используйте что-нибудь вроде 100000.
В дополнение к ответу Фелипе я хотел бы немного больше поделиться своим опытом использования 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 (последняя)
Лично я буду использовать
Number.MAX_SAFE_INTEGERвместо жестко запрограммированного2147483647. Это не тот номер, но это максимальное безопасное целое число.