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

如何解决异步爬虫函数返回对象无法赋值给变量的问题

问题排查与解决步骤

以下是按优先级排序的排查方向,都是这类问题的常见坑:

1. 确认getSharesInfo函数是否正确return了数据

这是最常见的原因:很多人在函数里打印了数据,但忘记return结果。单独执行时console能看到数据,但函数本身返回的是Promise<undefined>,所以await后shares自然为空。

错误示例:

async function getSharesInfo() {
  const res = await axios.get('目标URL');
  const $ = cheerio.load(res.data);
  const stockData = { /* 处理后的数据 */ };
  console.log(stockData); // 能输出,但没return
}

修正写法:

async function getSharesInfo() {
  const res = await axios.get('目标URL');
  const $ = cheerio.load(res.data);
  const stockData = { /* 处理后的数据 */ };
  console.log(stockData);
  return stockData; // 必须return结果
}

2. 确保Express路由的handler是async函数

如果路由回调没有声明为async,内部的await会无效,甚至可能静默失败(比如非async函数里用await会触发语法错误,或用then但未处理结果导致数据无法传递)。

错误示例:

// 非async回调,await不生效
app.get('/', (req, res) => {
  const shares = await getSharesInfo(); // 这里会直接报错,或静默返回Promise
  res.render('index', { shares });
});

修正写法:

// 声明为async回调,同时用try/catch捕获异常
app.get('/', async (req, res) => {
  try {
    const shares = await getSharesInfo();
    res.render('index', { shares });
  } catch (error) {
    console.error('获取股票数据失败:', error);
    res.status(500).send('数据加载失败');
  }
});

3. 检查getSharesInfo内部的错误处理是否吞掉了异常

如果函数内部用了try/catch但没有抛出错误或返回 fallback 数据,当请求失败时,函数会返回Promise<undefined>,导致await后shares为空且无报错。

错误示例:

async function getSharesInfo() {
  try {
    const res = await axios.get('目标URL');
    const $ = cheerio.load(res.data);
    const stockData = { /* 处理后的数据 */ };
    return stockData;
  } catch (err) {
    console.log('请求出错了'); // 只打印,没抛出或返回数据
  }
}

修正写法:

async function getSharesInfo() {
  try {
    const res = await axios.get('目标URL');
    const $ = cheerio.load(res.data);
    const stockData = { /* 处理后的数据 */ };
    return stockData;
  } catch (err) {
    console.error('爬取数据失败:', err);
    throw err; // 抛出错误让路由层处理
    // 或者返回默认值:return {}; 或 return [];
  }
}

4. 验证爬取的HTML结构是否符合预期

有些网站会根据请求头(比如User-Agent)返回不同内容,单独测试时用的是浏览器请求头,而Express中axios用的是Node环境默认头,可能被反爬返回空页面或验证码页面。

可以在getSharesInfo中把爬取到的HTML保存到本地,验证内容:

const fs = require('fs');
async function getSharesInfo() {
  const res = await axios.get('目标URL', {
    // 模拟浏览器请求头
    headers: {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36'
    }
  });
  // 保存HTML到本地
  fs.writeFileSync('test.html', res.data);
  const $ = cheerio.load(res.data);
  const stockData = { /* 处理后的数据 */ };
  return stockData;
}

打开test.html查看是否为预期的股票页面,如果是空白或验证码,说明需要调整请求头或处理反爬。

5. 排查是否有未被等待的异步操作

如果getSharesInfo内部用了then而非await处理异步操作,可能导致函数提前return,比如:

// 错误写法:then回调的return不会作为函数的返回值
async function getSharesInfo() {
  axios.get('目标URL').then(res => {
    const $ = cheerio.load(res.data);
    const stockData = { /* 处理后的数据 */ };
    return stockData;
  });
}

必须统一用await处理所有异步逻辑,确保函数在数据处理完成后再return。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 09:20:26