JavaScript, выполнение запросов POST и GET одновременно с использованием Promises - PullRequest
3 голосов
/ 05 марта 2019

Справочная информация : у меня есть функция, которая нуждается в небольшой отладке, которая связана с запросами API (POST, GET) и обещаниями.Последние несколько дней я пытался понять, как работают асинхронные функции, и оказывается, что невозможно (или я так слышал) напрямую возвращать значение из таких функций в синхронные функции.

Моя первоначальная идея заключалась в том, чтобысделать функцию запроса POST, которая возвращает токен доступа, который я мог бы подключить к заголовку авторизации моей функции GET (который прекрасно работает, пока предоставляется токен).Однако из моего открытия я не могу сделать это двумя отдельными методами, потому что запрос POST возвращает неопределенное значение вне функции.Поэтому моя идея сейчас состоит в том, чтобы включить запрос GET в POST, чтобы токен доступа можно было передавать напрямую без вызова метода.Я попытался сделать это, используя Обещания, с которыми я не очень хорошо знаком, но мне удалось найти какой-то смысл.Я ожидал, что я смогу вызвать функцию httpGetData(), которая сначала получит токен, а затем передаст его в часть .then(), которая должна возвращать фактические данные или [object Promise] вместо неопределенных.

Вопрос : Проблема в том, что когда я вызываю функцию httpGetData(), она возвращает undefined, но мой console.log(result[0]) ясно показывает, что запрос GET выбрал данные, которые я хочу.Мне было интересно, есть ли твик, который позволил бы моему коду вернуть эти данные (console.log для меня бесполезен, кроме как видеть, что происходит на фоне запроса API).Я видел несколько SO вопросов, на которые они ответили, возвращая значения в .then(), но все мои попытки вернули неопределенное значение.

Я приложил скриншоты выходных данных.Имейте в виду, что это лямбда-код навыка Alexa, поэтому возврат появляется после .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

возвращаемое изображение

Изображение журнала консоли

1 Ответ

0 голосов
/ 05 марта 2019

Я наконец-то решил проблему благодаря @Bergi.Хотя этот ответ можно сократить, я хочу опубликовать его, чтобы он мог служить опцией.Берги предложил, чтобы вместо выполнения запросов POST и GET в одной функции мы могли разделить их и использовать другую функцию для их одновременного выполнения.В приведенном ниже коде httpToken () выполняет запрос POST и возвращает токен доступа.Функция httpResource (accessToken) выполняет запрос GET, где принимает параметр accessToken.Другая функция, finalData () поможет нам выполнять запросы POST и GET одновременно, возвращая [объект Promise] вместо undefined, к которому мы можем получить доступ.Нашим последним шагом будет создание функции 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...
}
...