You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Google OAuth授权回调包装为Promise并返回API调用结果

问题分析

你遇到的核心问题是异步回调的特性导致返回值无法传递到外部:script.scripts.run是异步执行的,当你在回调函数里return resp.response.result时,这个return只是回调函数的返回值,而不是testAuth方法的返回值。外部调用goo.test_auth()时,方法会直接执行完毕并返回undefined,此时异步的API请求还没完成,自然拿不到结果。

解决方案:用Promise包装异步操作 + async/await处理异步流程

我们可以把异步的API调用包装成Promise,再通过async/await让异步代码的执行逻辑更接近同步代码,这样就能正确把结果返回给外部了。以下是具体的代码调整步骤:

1. 改造testAuth方法,用Promise包装API调用

把原来的回调式调用改成Promise风格,成功时resolve结果,失败时reject错误:

Goo.prototype.testAuth = function(auth) {
  return new Promise((resolve, reject) => {
    const script = google.script('v1');
    const cmd = {
      auth,
      resource: {
        function: 'test_auth',
        devMode: true
      },
      scriptId: '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
    };

    script.scripts.run(cmd, function(err, resp) {
      if (err) {
        const apiError = new Error('The API returned an error: ' + err);
        console.log(apiError.message);
        reject(apiError);
        return;
      }
      if (resp.error) {
        const scriptError = new Error('Script error message: ' + resp.error.details[0].error.errorMessage);
        console.log(scriptError.message);
        reject(scriptError);
        return;
      }
      console.log('resp from api call', resp.response.result);
      resolve(resp.response.result); // 将结果传递给Promise的调用者
    });
  });
};

2. 改造authorize方法,同样返回Promise

假设你的authorize方法是用来获取授权对象的,也要把它改成Promise风格(否则无法和后续的await配合):

Goo.prototype.authorize = function() {
  return new Promise((resolve, reject) => {
    // 这里替换成你原来的授权逻辑,比如读取密钥、获取OAuth token等
    // 示例:假设原来的授权是回调式的
    google.auth.getClient({
      // 你的授权配置,比如keyFile、scopes等
    }, (err, auth) => {
      if (err) {
        reject(new Error('Authorization failed: ' + err));
        return;
      }
      resolve(auth);
    });
  });
};

3. 改造test_auth方法为async函数

用async/await串联授权和API调用的异步流程,最终返回结果:

Goo.prototype.test_auth = async function() {
  try {
    const auth = await this.authorize(); // 等待授权完成,拿到auth对象
    const result = await this.testAuth(auth); // 等待API调用完成,拿到结果
    return result; // 结果会被包装成Promise返回给外部
  } catch (err) {
    console.error('Error in test_auth:', err);
    throw err; // 将错误抛出,让外部调用者处理
  }
};

4. 外部调用时处理异步结果

因为test_auth现在返回的是Promise,外部需要用await(在async函数内)或者.then()来获取结果:

const Goo = require('./Goo.js');
const goo = new Goo();

// 方式1:用async/await(推荐,代码更简洁)
async function main() {
  try {
    const response = await goo.test_auth();
    console.log('response to use elsewhere ', response);
    // 在这里可以正常使用response做后续操作
  } catch (err) {
    console.error('Failed to get API response:', err);
  }
}

main();

// 方式2:用.then()/.catch()(兼容老代码风格)
goo.test_auth()
  .then(response => {
    console.log('response to use elsewhere ', response);
  })
  .catch(err => {
    console.error('Failed to get API response:', err);
  });
额外优化:利用googleapis的Promise支持

你使用的googleapis@24.0.0版本已经支持Promise化调用——当你调用API方法时不传入回调函数,它会直接返回一个Promise。基于这个特性,testAuth可以简化成更简洁的async函数:

Goo.prototype.testAuth = async function(auth) {
  const script = google.script('v1');
  const cmd = {
    auth,
    resource: {
      function: 'test_auth',
      devMode: true
    },
    scriptId: '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
  };

  try {
    const resp = await script.scripts.run(cmd);
    if (resp.error) {
      const scriptError = new Error('Script error message: ' + resp.error.details[0].error.errorMessage);
      console.log(scriptError.message);
      throw scriptError;
    }
    console.log('resp from api call', resp.response.result);
    return resp.response.result;
  } catch (err) {
    console.log('The API returned an error: ' + err);
    throw err;
  }
};

这样代码会更清爽,也省去了手动包装Promise的步骤。

内容的提问来源于stack exchange,提问作者Rob Foree

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:34:49