Using native javascript promises in postman

Hi,

Javascript and node now has native support for Promises. I was hoping we could use these in Postman and newman as well to chain async sendRequest calls.

Although declaring and using new Promise works but chaining does not work.

For example look at the code below (put this in test script of any request)

var promiseMethod = function(text) {
   var promise = new Promise(function(resolve, reject){
      console.log('Enter: ' + text);
      setTimeout(function() {
         console.log('Complete: ' + text);
         resolve({data: text + ' 123'});
      }, 2000);
   });
   return promise;
};

promiseMethod('first')
   .then((v) => {return promiseMethod('second');})
   .then((v) => {return promiseMethod('third');})

The Postman Console output for this is:

Enter: first
Complete: first
Enter: second

Whereas if run through NODE or even Chrome console, the output is:

Enter: first
Complete: first
Enter: second
Complete: second
Enter: third
Complete: third

Whats the reason, that only the 1st Promise call is handled by postman/newman but chained calls do not work ?

1 Like

Hi @aksbenz This is a known issue - we’re working to get this working correctly. As a temporary workaround, you can use this:

 var interval = setTimeout(function() {}, 10000),
  promiseMethod = function(text) {
   var promise = new Promise(function(resolve, reject){
      console.log('Enter: ' + text);
      setTimeout(function() {
         console.log('Complete: ' + text);
         resolve({data: text + ' 123'});
      }, 2000);
   });
   return promise;
};

promiseMethod('first')
   .then((v) => {return promiseMethod('second');})
   .then((v) => {return promiseMethod('third');})
   .then((v) => {clearTimeout(interval);})

This essentially adds a timeout that’s closed when all promises are resolved. This makes the Postman script module to wait till that time before proceeding to send the request.

Hi @abhijit do you have any update on this? are promises working properly with the latest version of postman?

We are evaluating Postman as a platform to run our E2E tests on and not having promises seriously impacts our ability to write non-trivial scripts.

Currently, I need to do 3 API calls to setup the application to be ready for testing. With callbacks this is seriously hell.

2 Likes

I need to use the result of the promise as an environment variable - but it seems it’s getting set too late. Any suggestions?

"use strict";
var lock = setTimeout(function() {}, 3000);
var secret = '<redacted>';

postman.setEnvironmentVariable("nonce", Math.ceil(new Date().getTime() / 1000));

hash('SHA-256', secret + '' + postman.getEnvironmentVariable('nonce')).then(function(sha) {
    postman.setEnvironmentVariable("nonce_token", sha);
    clearTimeout(lock);
});


console.log(hash('SHA-256', secret + '' + postman.getEnvironmentVariable('nonce')));

async function hash(digest, inputString) {
	return Array.from(new Uint8Array(crypto.subtle.digest(digest, new TextEncoder("utf-8").encode(inputString)))).map(b => (b.toString(16).padStart(2, "0"))).join('');
}

Edit:
Worked around the issue using

require("crypto-js");
CryptoJS.SHA256(secret + '' + postman.getEnvironmentVariable('nonce')).toString(CryptoJS.enc.Hex);

Hey guys, thanks for the tips here. I had the same issue and just documented the solution (using a global setTimeout) at Stack Overflow.

Hello All,

Postman Tests with chained promises is executing only the first promise but not chained promises. I am not sure whats wrong with this code but it is executing only 1st promise and ignoring the rest.

I have tried based on the above solution but didn’t work. Kindly help me in this regard.

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.log(err);
                reject();
            } else {
                console.log(`Resolved promise ${++promiseNumber}`);
                resolve(pm.response.to.have.status(200));
            }
        });
    });
}

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

Thanks
Dinesh

It doesn’t seem to work in the newer versions of postman. I have tried numerous iterations of this solution to no luck. I have found that going to a lovely (/sarcasm) callback approach works…

let promiseNumber = 0;
function resolvedPromise(cb) {
        pm.sendRequest('https://postman-echo.com/get', (err, res) => {
            if (err) {
                console.log(err);
                cb(err);
            } else {
                console.log(`Resolved promise ${++promiseNumber}`);
                cb(res.json());
            }
        });
}

resolvedPromise(()=>resolvedPromise(()=> resolvedPromise(()=>{})))
1 Like

Any update on this? Is it confirmed that the setTimeout technique for chaining promises with pm.sendRequest is NOT working in the latest version of Postman sandbox?

I’m on 7.22.1 and I also cannot seem to get the setTimeout work around to work either.