Невозможно вернуть значение при использовании функции asyn c в nodejs - PullRequest
0 голосов
/ 26 апреля 2020

Попытка вернуть значение после вызова API Google в приведенной ниже функции asyn c в облачной функции Google

 async function getGoogleApiToken() {
      let jwtClient = new google.auth.JWT(
               privatekey.client_email,
               null,
               privatekey.private_key,
               ['https://www.googleapis.com/auth/compute']);
        //authenticate request
       await jwtClient.authorize(function (err, tokens) {
         if (err) {
           console.log(err);
           return;
         } else {
           console.log("Successfully connected!"+ tokens.access_token); //displaying the token correctly
           return tokens.access_token; //returns the token
         }
        });
    }
  exports.consumepromise = async (req,res) =>{
  const tokennew =  await getGoogleApiToken();
  console.log("token"+tokennew);
  }

Ошибка: tokennew не определено

Не уверен, куда он идет неправильно.

Ответы [ 2 ]

2 голосов
/ 26 апреля 2020

Если бы мне пришлось угадать, это потому, что jwtClient.authorize принимает обратный вызов вместо возврата обещания -

async function getGoogleApiToken() {
  let jwtClient = new google.auth.JWT(...);
  await jwtClient.authorize(function (err, tokens) {
    if (err) {
      console.log(err);
      return;
    } else {
      console.log("Successfully connected!"+ tokens.access_token); //displaying the token correctly
      return tokens.access_token; //returns the token // <- NO IT DOESN'T
    }
  });
}

Обратные вызовы не могут return значение. Это один из самых популярных вопросов в StackOverflow. Обратные вызовы, подобные тем, которые используются в jwtClient.authorize, являются просто распространенным шаблоном использования и не взаимодействуют напрямую с async и await. Вы должны вернуть Promise из вашего getGoogleApiToken. Один из таких способов - обернуть Обещание вокруг вызова jwtClient.authorize -

async function getGoogleApiToken() {
  const jwtClient = new google.auth.JWT(...); // <-- btw use const
  return new Promise((resolve, reject) => // <-- wrap in promise
    jwtClient.authorize((err, tokens) => {
      if (err)
        reject(err) // <-- reject the error
      else
        resolve(tokens) // <-- resolve the result
    })
  )
}

. Мы не хотим добавлять эту обёртку Обещания каждый раз, когда мы sh используем функцию приема обратного вызова с другими Код на основе обещаний, включая любые функции async. Превращение любой асин c, принимающей функцию обратного вызова, в асин c, возвращающую обещание, может быть механическим процессом. Фактически это то, что NodeJS s util.promisify делает. Это работает примерно так -

// approximation of util.promisify
const promisify = f => (...args) =>
  new Promise ((pass, fail) =>
    f (...args, (err, result) => err ? fail(err) : pass(result))
  )

// example callback-accepting function
const demoCallbackFunc = (a, b, callback) =>
  setTimeout(callback, 1000, null, a + b)

// ordinary call
demoCallbackFunc(3, 5, (err, res) => {
  if (err)
    console.error(err)
  else
    console.log(res)
})

// promisified
promisify(demoCallbackFunc)(3, 5)
  .then(console.log, console.error)

console.log("please wait 1 second...")

Использование promisify в вашей программе значительно очистит его -

async function getGoogleApiToken() {
  const jwtClient = new google.auth.JWT(...);
  const auth = promisify(jwtClient.authorize.bind(jwtClient))
  return auth() // <-- no need for await, auth already returns a promise
}

Или без промежуточного назначения auth -

async function getGoogleApiToken() {
  const jwtClient = new google.auth.JWT(...);
  return promisify(jwtClient.authorize.bind(jwtClient))()
}

или без bind с использованием функции стрелки -

async function getGoogleApiToken() {
  const jwtClient = new google.auth.JWT(...);
  return promisify(callback => jwtClient.authorize(callback))()
}
0 голосов
/ 26 апреля 2020

const tokennew = await getGoogleApiToken(); должен быть внутри блока asyn c, или вы можете использовать .then и .catch для него следующим образом:

с блоком asyn c

  async function consumePromise() {
   const tokennew =  await getGoogleApiToken();
   console.log("token"+tokennew);
  }
  // then call it
  consumePromise();

с помощью then и catch

   getGoogleApiToken()
     .then(tokennew => {
       console.log("token"+tokennew);
     })
     .catch(err => {
       console.log(err);
     })

Здесь важно отметить, что вы не можете получить доступ к значению, разрешенному обещанием вне блока asyn c или без использования .then и .catch в обещание.

...