JavaScript,使用Promises同时发出POST和GET请求

时间:2019-03-05 16:35:34

标签: javascript node.js post promise get

背景:我有一个函数,该函数需要与API请求(POST,GET)和Promise相关的小型调试。在过去的几天里,我一直在尝试弄清楚异步函数是如何工作的,结果证明,不可能(或者我听说)直接将值从此类函数返回给同步函数。

我最初的想法是制作一个POST请求函数,该函数返回一个访问令牌,我可以将其插入到我的GET函数的授权标头中(只要提供了令牌,它就可以完美地工作)。但是,根据我的发现,我无法在两个单独的方法上执行此操作,因为POST请求在函数外部返回未定义。因此,我现在的想法是将GET请求包含在POST中,以便访问令牌可以直接传递而无需任何方法调用。我尝试使用我不太熟悉但有一定道理的Promises来做到这一点。我的期望是,我可以调用httpGetData()函数,该函数首先获取令牌,然后将其传递到.then()部分,该部分应该返回实际数据或[object Promise]而不是未定义的数据。

问题:问题是,当我调用httpGetData()函数时,它返回undefined,但是我的console.log(result[0])清楚地表明GET请求已获取数据我想要。我想知道是否有一个调整允许我的代码返回该数据(console.log对我来说是无用的,除了查看api请求的背景是什么)。我看到这样的问题通过返回.then()中的值得到了解答,但是我的尝试都未定义。

我已经附上了输出的屏幕截图。请记住,这是Alexa技能的Lambda代码,因此返回值出现在.speak()之后,并且console.log显示如下。

function httpGetData() {

  var promise1 = new Promise(((resolve, reject) => {
    var options = {
      method: "POST", // POST request intended to get access token
      host: 'hostinfo',
      path: "pathinfo",                                                        
      headers: {
        "content-type": "stuff here",
        "cache-control": "no-cache",
     }
  };

  var request = http.request(options, function (response) {
    var returnData = [];

    response.on("data", function (chunk) {
      returnData += chunk;
    });

    response.on("end", function () {
      var data = JSON.parse(returnData);
      var accessToken = data.access_token; // the access token value of the POST api request like "039509544932n3249fc21232nc32423nci"
      resolve(accessToken);
    });

    response.on('error', (error) => {
      reject(error);
    });
  });

  request.write("------stuff: form-data; name=\"client_secret\"\r\n\r\stuff here\r\n------stuff: form-data; name=\"client_id\"\r\n\r\stuff here\r\n------stuff: form-data; name=\"grant_type\"\r\n\r\nclient_credentials\r\n------stuff");
  request.end();

  }));

  promise1.then(function(value) {
      return new Promise(((resolve, reject) => {
        var options = {
          method: "GET", //this is a GET request so it's intended to get usable data using access token
          host: 'hostinfo',
          path: "pathinfo",                
          headers: {
            "content-type": "stuff here",
            "Authorization": "Bearer " + value, // value is the access token that was resolved earlier ("039509544932n3249fc21232nc32423nci") so I'm trying to concatonate this to the authorization header
            "cache-control": "no-cache",
         }
    };

      var request = http.request(options, function (response) {
        var returnData = [];

        response.on("data", function (chunk) {
          returnData += chunk;
        });

        response.on("end", function () {
          console.log(value); //this is the line that prints access token in screenshot
          resolve(JSON.parse(returnData));
        });

        response.on('error', (error) => {
          reject(error);
        });
      });

      request.write("------stuff: form-data; name=\"client_secret\"\r\n\r\stuff here\r\n------stuff: form-data; name=\"client_id\"\r\n\r\stuff here\r\n------stuff: form-data; name=\"grant_type\"\r\n\r\nclient_credentials\r\n------stuff");
      request.end();

        }))
  }).then((result) => {
            console.log('hello');
            return result; //I'm not sure here but wanted to return the result 
            }).then((result) => {
                  console.log(result[0]); // just a check which shows that result[0] actually executes and can be printed as shown in screenshot
                  return result[0]; //other desperate attempt


});


}// httpGetData() function ends here

return image

Console log image

1 个答案:

答案 0 :(得分:0)

由于@Bergi,我终于解决了问题。尽管可以缩短此答案,但我希望将其发布,以便可以将其用作选项。 Bergi的建议是,我们不必将POST和GET请求都在一个函数中完成,而是可以将它们分开,然后使用另一个函数来同时执行它们。在下面的代码中, httpToken()执行POST请求并返回访问令牌。 httpResource(accessToken)函数执行一个GET请求,该请求将带有一个accessToken参数。另一个函数 finalData()将帮助我们同时发出POST和GET请求,因此返回一个 [object Promise] 而不是未定义的,我们可以访问它。我们的最后一步将是具有async / await函数( retrieveInfo()),该函数将使用finalData()从请求中获取响应。享受吧!

function httpToken() {
  return new Promise(((resolve, reject) => {
    var options = {
      method: "POST",
      host: 'hostinfo',
      path: "pathinfo",                                                        
      headers: {
        "content-type": "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
        "cache-control": "no-cache",
     }
  };

  var request = http.request(options, function (response) {
    var returnData = [];

    response.on("data", function (chunk) {
      returnData += chunk;
    });

    response.on("end", function () {
      var data = JSON.parse(returnData);
      var accessToken = data.access_token;
      resolve(accessToken); //resolving access token (can be changed to resolve(data) to include timestamp etc)
    });

    response.on('error', (error) => {
      reject(error);
    });
  });

  request.write("------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"client_secret\"\r\n\r\n"client secret here"\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"client_id\"\r\n\r\n"client id here"\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"grant_type\"\r\n\r\n"grant type here"\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--");
  request.end();

  }));
}


function httpResource(accessToken){
      return new Promise(((resolve, reject) => {
        var options = {
          method: "GET",
          host: 'hostinfo',
          path: "pathinfo",                                                       
          headers: {
            "content-type": "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
            "Authorization": "Bearer " + accessToken,
            "cache-control": "no-cache",
         }
    };

      var request = http.request(options, function (response) {
        var returnData = [];

        response.on("data", function (chunk) {
          returnData += chunk;
        });

        response.on("end", function () {
          resolve(JSON.parse(returnData));
        });

        response.on('error', (error) => {
          reject(error);
        });
      });

      request.write("------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"client_secret\"\r\n\r\n"client secret here"\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"client_id\"\r\n\r\n"client id here"\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"grant_type\"\r\n\r\n"grant type here"\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--");
      request.end();


    }));
}

function finalData()
{
  return httpToken().then(token => httpResource(token));
}

async function retrieveInfo()
{
    response = await finalData(); //response will have the data returned from our GET request using finalData()

    //do stuff with response...
}