Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Postman / pm api sendRequest command: how to wait till the response is back before populating the variable?

I am trying to create a dictionary object of the response json's using postman's pm api sendRequest.

Wrote a recursive function to get all the responses but the problem is the response dictionary object population happens way before even the response comes back.

Is there any way to wait the dictionary population before each of the respective response is received so as to capture the response within the dictionary object ?

var respDictionary  = {};

getResponses (listOfUrls);

console.log("respDictionary: ");
console.log(respDictionary);

function getResponses(urlList) {

    if (typeof urlList === 'string') {
        urlList = urlList.split(' ');
    }
    _url = urlList[0];

    var call = {
        url: _url ,
        method: 'GET',
        header: {
            "Authorization": `Bearer ${token}`,
            "Content-Type": "application/json"
        }
    };
    urlList.splice(0, 1);

    pm.sendRequest(
        call,
        function (err, res) {
        if (err) {
            console.log(err);
        } else {
            if (urlList.length === 0) {
                return;
            }
            try {
                respDictionary[_url] = res.json();
            } catch (e) {
                console.log(err);
            }
            getResponses(urlList);
        }
    });
    console.log(respDictionary);
}

Output is:

respDictionary:
Object:{}
//further, pm request responses are listed
like image 744
overflower Avatar asked Nov 21 '17 05:11

overflower


2 Answers

Apart from the other answer(s), following simple approach also works well instead of recursion:

_.forEach (
    urls,
    function (urls) {
        getAPI(url,function (url,schema,err) {            
            if (!err) {                
                respDictionary[url]=resp.json();
                console.log(schema);
            } else {                
                console.log(err);
            }
            pm.environment.set('respDictionary', JSON.stringify(respDictionary));
        });
    }
);

function getAPI(url, callback) {
    var _url = '{{BP_SERVER}}/' + urls;
    var call = {
        url: _url,
        method: 'GET',
        header: {
            "Authorization": `Bearer ${token}`,
            "Content-Type": "application/json"
        }
    };  

    pm.sendRequest(
        call,
        function (err, res) {
            if (!err) {             
                callback(urls,res.json());
            } else {                
                callback(urls,'',err);
            }
        }
    );
}
like image 37
overflower Avatar answered Sep 21 '22 15:09

overflower


You do not understand JavaScript asynchrounous handling. Maybe the following will help:

  • Event loop video

  • Promises

  • Event loop documentation (video is easier)

Your code will work if you use promises:

function getResponses(urlList) {

  if (typeof urlList === 'string') {
    urlList = urlList.split(' ');
  }
  return Promise.all( 
    urlList.map(
      function(url){
        return {
          url: url ,
          method: 'GET',
          header: {
            //not sure where token comes from
            "Authorization": `Bearer ${token}`,
            "Content-Type": "application/json"
          }
        };
      }
    ).map(
      function(call){
        return new Promise(
          function(resolve,reject){
            pm.sendRequest(
              call,
              function (err, res) {
              if (err) {
                reject(err);
              } else {
                resolve([call.url,res.json()]);
              }
            });
          }
        )
        .then(
          undefined
          ,function(err){
            //if something goes wrong we will still return something
            return [call.url,{error:err}];
          }
        )
      }
    )
  )
  .then(
    function(results){
      return results.reduce(
        function(acc,result){
          acc[result[0]] = result[1];
        }
        ,{}
      );
    }
  )
}
getResponses (listOfUrls)
.then(//this will always succeed, failed items have {error:something}
  function(results){
    console.log("results:",results);
  }
);
console.log("this comes before results");

The code above will cause all request to happen at once, this may not be the desired behavior, I have written a throttle method that is part of some library functions that may come in handy. You can apply the throttle to your code so it will only have max amount of connections:

const max = 10;//maximum 10 active connections
function getResponses(urlList) {  
  const throttled = throttle(max);
  if (typeof urlList === 'string') {
    urlList = urlList.split(' ');
  }
  return Promise.all( 
    urlList.map(
      function(url){
        return {
          url: url ,
          method: 'GET',
          header: {
            //not sure where token comes from
            "Authorization": `Bearer ${token}`,
            "Content-Type": "application/json"
          }
        };
      }
    ).map(
      throttled(//only max amount of connections active at any time
        function(call){
          return new Promise(
            function(resolve,reject){
              pm.sendRequest(
                call,
                function (err, res) {
                if (err) {
                  reject(err);
                } else {
                  resolve([call.url,res.json()]);
                }
              });
            }
          )
          .then(
            undefined
            ,function(err){
              //if something goes wrong we will still return something
              return [call.url,{error:err}];
            }
          )
        }
      )
    )
  )
  .then(
    function(results){
      return results.reduce(
        function(acc,result){
          acc[result[0]] = result[1];
        }
        ,{}
      );
    }
  )
}
getResponses (listOfUrls)
.then(//this will always succeed, failed items have {error:something}
  function(results){
    console.log("results:",results);
  }
);
console.log("this comes before results");
like image 82
HMR Avatar answered Sep 18 '22 15:09

HMR