Postman / pm api sendRequest 命令:如何等到响应返回后再填充变量?

Posted

技术标签:

【中文标题】Postman / pm api sendRequest 命令:如何等到响应返回后再填充变量?【英文标题】:Postman / pm api sendRequest command: how to wait till the response is back before populating the variable? 【发布时间】:2018-05-04 11:24:55 【问题描述】:

我正在尝试使用邮递员的 pm api sendRequest 创建响应 json 的字典对象。

编写了一个递归函数来获取所有响应,但问题是响应字典对象填充发生在响应返回之前。

有没有办法在接收到每个相应的响应之前等待字典填充,以便在字典对象中捕获响应?

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);

输出是:

respDictionary:
Object:
//further, pm request responses are listed

【问题讨论】:

我更新了我的答案,在您的代码中,下一个 url 将在前一个 URL 完成后打开(串行)。我的代码会立即打开所有网址。对于大量的 url,最好限制打开连接的数量,所以我添加了一个限制。 【参考方案1】:

除了其他答案之外,以下简单方法也可以很好地代替递归:

_.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);
            
        
    );

【讨论】:

【参考方案2】:

您不了解 javascript 异步处理。也许以下内容会有所帮助:

Event loop video

Promises

Event loop documentation(视频更简单)

如果您使用 Promise,您的代码将起作用:

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");

上面的代码会导致所有请求同时发生,这可能不是我们想要的行为,我写了一个throttle method,它是一些可能派上用场的库函数的一部分。您可以将油门应用于您的代码,这样它就只有最大数量的连接:

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");

【讨论】:

以上是关于Postman / pm api sendRequest 命令:如何等到响应返回后再填充变量?的主要内容,如果未能解决你的问题,请参考以下文章

postman 脚本学习

温故知新,.Net Core遇见Postman(API Development),进阶分布式微服务高效调式

Postman的pm对象

postman之pm对象详解

postman——集合——执行集合——测试脚本——pm对象简单示例02

postman常用断言