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

如何让JavaScript函数返回异步调用获取的值?

解决异步函数返回值的问题

你的问题核心就是JavaScript异步操作的执行顺序导致的——getNumPages里的同步代码会先跑完,而makeRequest的回调要等异步请求完成后才执行,所以return的时候totalPages还是初始值0。要让getNumPages能返回异步获取到的页数,得用Promise或者async/await来处理,下面给你几种可行的方案:

方案1:让getNumPages返回Promise

把getNumPages改成返回一个Promise,在makeRequest的回调里resolve结果:

const https = require('https');

function getNumPages(substr) {
  return new Promise((resolve) => {
    console.log(`Before makeRequest`);
    makeRequest(substr, (numPages) => {
      console.log(`Inside callback from makeRequest: ${numPages}`);
      // 异步操作完成后,把结果传递出去
      resolve(numPages);
    });
  });
}

// 调用方式:用then获取结果
getNumPages('Shakespeare')
  .then(totalPages => {
    console.log(`最终页数:${totalPages}`); // 这里就能拿到正确的79了
  });

如果makeRequest可能出现错误(比如请求失败),记得加上reject来处理错误:

function getNumPages(substr) {
  return new Promise((resolve, reject) => {
    makeRequest(substr, (numPages, err) => {
      if (err) {
        reject(err);
        return;
      }
      resolve(numPages);
    });
  });
}

// 调用时加上catch处理错误
getNumPages('Shakespeare')
  .then(totalPages => console.log(totalPages))
  .catch(err => console.error('请求出错:', err));

方案2:用async/await简化代码

async/await是Promise的语法糖,写起来更像同步代码。首先需要把makeRequest包装成返回Promise的函数,或者直接改造它:

第一步:包装makeRequest为Promise版本

function makeRequestPromise(substr) {
  return new Promise((resolve, reject) => {
    makeRequest(substr, (numPages, err) => {
      if (err) reject(err);
      else resolve(numPages);
    });
  });
}

第二步:把getNumPages改成async函数

async function getNumPages(substr) {
  console.log(`Before makeRequest`);
  // 用await等待Promise完成,拿到结果
  const totalPages = await makeRequestPromise(substr);
  console.log(`After makeRequest: ${totalPages}`);
  return totalPages;
}

调用方式

因为async函数返回的还是Promise,所以可以在另一个async函数里用await,或者用then:

// 顶层await需要在async IIFE里(Node.js环境支持)
(async () => {
  try {
    const pages = await getNumPages('Shakespeare');
    console.log(pages); // 79
  } catch (err) {
    console.error(err);
  }
})();

为什么原来的代码不行?

简单说,JavaScript是单线程的,异步操作(比如你的https请求)会被放到事件队列里,当前的同步代码(console.log('After makeRequest')和return totalPages)会先执行完毕,等异步请求完成后,才会从事件队列里取出回调函数执行。所以return的时候,totalPages还没被赋值,自然返回0。

进阶:直接改造makeRequest为Promise版本

如果makeRequest是你自己写的,最好直接让它返回Promise,避免额外的包装:

function makeRequest(substr) {
  return new Promise((resolve, reject) => {
    // 这里写你的https请求逻辑,比如:
    const url = `https://your-api-url?substr=${encodeURIComponent(substr)}`;
    https.get(url, (res) => {
      let rawData = '';
      res.on('data', (chunk) => { rawData += chunk; });
      res.on('end', () => {
        try {
          const result = JSON.parse(rawData);
          const numPages = result.totalPages; // 假设API返回的结构里有totalPages
          resolve(numPages);
        } catch (e) {
          reject(e);
        }
      });
    }).on('error', (e) => {
      reject(e);
    });
  });
}

这样getNumPages就可以直接用await调用它,代码更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:38:34