How to send GET request synchronusly within loop?

I searched community and found answers about synchronous executions but none of them suits my needs. In my case repetition number is unknow, depends on response (or timeout). Chaining and nesting is not solution.
I have many PUT requests that executes asyncronously. Request returns “Accepted” and in header “Location” to query execution status. Next I make GET to get status of long running operation. Sleep and make GET again till resource is created (or error).

My current collection looks like:
PUT
Post-response script:
const location = pm.response.headers.get(‘location’);
pm.collectionVariables.set(“LOCATION”, “location”);

GET request queries LOCATION and if status is 206, script waits and reruns GET
GET {{SERVER}}{{LOCATION}}
Pre-request script
var sleepBetweenRetries = 10000;
setTimeout(function() {}, sleepBetweenRetries);

Post-response script
const statusPartialContent = 206;
if(pm.response.code == statusPartialContent) {
pm.execution.setNextRequest(pm.info.requestName);
}
I have a dozen of PUT requests in my collection and affter every PUT one GET. GET is copy/paste of single GET.

I would like to remove GET requests and add logic to PUT Post-response script. Then use pm.sendRequest() in loop, to query status of long running operation.
If status is 206, wait and do GET again. If timeout expired or error returnd from GET, stop procesing. If 201 returned, continue.
As you see, number of iterations is unknown and each GET must run when timeout expires, resource created or error encountered.

I’m not sure what your question is.

If you want to move your GET request to a post response script, then that should be fine.

The asynchronous nature of sendRequest will not matter if you are just looping on the same request. It only matters when you have more than one request in the same scripting tab as you can’t guarantee the order without some extra logic.

Create the sendRequest(), and have your IF statement checking the status code to control your loop. This should be fine.

Best practice though is to have a counter to break the loop to prevent endless loops from occurring. So you might want to consider the robustness of your IF statement. What should happen if something other than 201 or 206 is returned?

If you put pm.sendRequest() in Post-response script, Postman will not wait for result (since it is async operation). Postman will continue with next request in collection.
Please try simple test.
-Create workspace with two GET requests
-Put sleep (10 seconds) in Post-response of workspace and add some log printing after sleep.

Postman will execute first request, then second and about 10 second later you will get 2 log print rows. One for each request.
Identical case is with pm.sendRequest(). It is async function

I solved problem by wrapping pm.sendRequest() in async/await
-Created function which returns Promise. Promise wraps pm.sendRequest
-Created async wrapper function
-Inside async function invoked **await for Promise function **
-Post-response script invokes wrapper function.
Although Post-response script execution finishes, Postman does not continue with next request execution till Promises are resolved (or failed)

Using promises is the normal way of ensuring the order of async requests/operations.

I duplicated your test against Postman Echo.

The tests tab for request 1 has the following.

var sleepBetweenRetries = 10000;
setTimeout(function() {}, sleepBetweenRetries);
console.log("request1");

The tests tab for request 2 is the same but it console logs request2 instead.

This runs request 1 and shows the console log immediately, but then waits ten seconds before request 2 is run.

Request 1 fully completes before request 2 is run.

image

So if you have a single sendRequest(), this would usually complete before the next request is run.

It’s usually when you want to run more than one sendRequest() in your scripts that you then need to use the async wait and promise method to ensure order of operations.

For the second test, I just replaced all of the code in the tests tab for the first request with a sendRequest to Postman Echo (but using a Post request this time).

pm.sendRequest({
    url: 'https://postman-echo.com/post',
    method: 'POST',
    header: {
        'content-type': 'application/json'
    },
    body: {
        mode: 'raw',
        raw: JSON.stringify([
             { key: "test", value: 'request2' }
        ])
    }
}, (err, res) => {
    if (err) {
        console.log(err);
    } else {
        pm.test("Status code is 200", function () {
            pm.expect(res).to.have.status(200);
            let resJson = res.json();
            console.log("request2");
            // console.log(resJson);
        });
    }
});

console.log("request1");

The requests and console logs are as expected.

image

“request1” gets logged first because the code within sendRequest() is async, but “request2” will always get console logged before the 3rd request is run.

My understanding (which may be incorrect) that the asynchronous nature applies to the scripting processor that runs the script. Therefore, the pre-request script will always complete before the request is sent, and the tests tab will always complete before it passes the request into the next request. It’s not async between individual requests or even between the pre-request and post-response scripts.

The problem comes when you try and run two async operations within the same scripting window.

It would also be worthwhile with you sharing the solution, as a good example using promises and async/await would be useful for the search engine.

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.