I'm currently struggling with a problem regarding pm.sendRequest in Postman Pre-request script. I'm trying to run a Request within a for loop, but something it doesn't work properly.
Pre-request Script
var numberOfCampaigns = 2; //this number can have any value from 1 to 20)
for (var j = 0; j < numberOfCampaigns; j++) {
console.log(`J1:` + j);
var request_call = {
url: pm.environment.get("api-url"),
method: "POST",
header: {
"content-type": "text/xml",
SOAPAction: "add",
},
body: {
mode: "raw",
raw: "some-body"},
};
pm.sendRequest(request_call, (err, res) => {
if (err) {
} else {
console.log(`J2:` + j);
length = 2
for (var i = 0; i < length; i++) {
pm.environment.set(`someVariable_` + i + `_` + j, responseJson[i]);
console.log(`someVariable:`+i+`_`+j+`:`+ pm.environment.get(`someVariable_` + i + `_`+j));
}
}
});
console.log(`J3:` + j);
}
Console output:
J1:0
J3:0
J1:1
J3:1
POST https://api-url/
J2:2
someVariable_0_2:...
someVariable_1_2:...
POST https://api-url/
J2:2
someVariable_0_2:...
someVariable_1_2:...
GET https://api-url2/ (The actual Request)
I don't understand why the J2 console output is 2 instead of being 1 for the first Request then 2 for the second Request
Could you please help ?
UPDATE
After @Keith response I tried to make some changes:
var numberOfCampaigns = 2
const _dummy = setInterval(() => {}, 300000 );
function sendRequest(req) {
return new Promise((resolve, reject) => {
pm.sendRequest(req, (err,res) => {
if (err) {
console.log(err);
return reject(err);
}
console.log(`J2:` + j);
for (let i = 0; i < length; i++) {
pm.environment.set(`someVariable_` + i + `_` + j, responseJson[i]);
console.log(`someVariable:`+i+`_`+j+`:` + pm.environment.get(`someVariable_` + i + `_`+j));
}
return resolve(res);
})
});
}
(async function main() {
for(var j=0; j<numberOfCampaigns; j++){
var request_call = {
url: pm.environment.get("api-url"),
method: "POST",
header: {
"content-type": "text/xml",
SOAPAction: "add",
},
body: {
mode: "raw",
raw: pm.environment.get(`parameter`+j},
};
await sendRequest(request_call);
clearInterval(_dummy);
}
})();
Your scripts are asynchronous - pm.sendRequest
makes the request and calls your callback function when that request completes.
That may take varying amounts of time.
I would expect your script to start:
J1:0
J3:0
J1:1
J3:1
Because all of those are synchronous.
J2:
will appear when your HTTP requests return, but by then your loop will have finished, so they will both show J2:2
.
Note that i
will work because it's inside your callback function, and var j
is global - JS doesn't apply closures to loops or blocks unless you use let j
and the callback would keep the reference to it anyway.
You may even get the someVariable
logs out of order because the requests won't queue - whatever server may finish the second request before the first one.
The best way to avoid this is with await
or Promise.all
to makes sure that your JS outside of the callback doesn't run until the async actions have finished.