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

如何在循环中多次调用异步函数PageSpeedCall?

如何在循环中多次调用异步的PageSpeedCall方法

嘿,我来帮你搞定这个异步循环调用的问题~首先得先调整一下你的原函数,因为它现在硬编码了websites[0],没法动态传入不同的网站地址,然后再根据你的需求选择串行或并行的调用方式,毕竟异步操作在循环里很容易出现顺序混乱或者并发超限的问题。

第一步:改造原函数,支持动态传参并完善错误处理

你的原函数是回调风格的,而且缺少错误处理逻辑,我们先把它改成能接收目标网站参数,同时补上错误处理:

// 改造后的回调版函数,支持传入要检测的网站
function PageSpeedCall(site, callback) {
  const pagespeedCall = `https://www.googleapis.com/pagespeedonline/v4/runPagespeed?url=https://${site}&strategy=mobile&key=${keys.pageSpeed}`;
  let results = '';
  
  https.get(pagespeedCall, resource => {
    resource.setEncoding('utf8');
    resource.on('data', data => {
      results += data;
    });
    resource.on('end', () => {
      callback(null, results);
    });
    // 处理响应流的错误
    resource.on('error', err => {
      callback(err);
    });
  })
  // 处理get请求本身的错误
  .on('error', err => {
    callback(err);
  });
}

如果更习惯现代JS的Promise/async-await写法,也可以把它封装成Promise版本,后续处理循环会更顺手:

// 封装成Promise版本的函数
function pageSpeedCall(site) {
  return new Promise((resolve, reject) => {
    const pagespeedCall = `https://www.googleapis.com/pagespeedonline/v4/runPagespeed?url=https://${site}&strategy=mobile&key=${keys.pageSpeed}`;
    let results = '';
    
    https.get(pagespeedCall, resource => {
      resource.setEncoding('utf8');
      resource.on('data', data => {
        results += data;
      });
      resource.on('end', () => {
        resolve(results);
      });
      resource.on('error', err => {
        reject(err);
      });
    })
    .on('error', err => {
      reject(err);
    });
  });
}

第二步:循环调用的两种方案

方案1:串行调用(逐个执行,适合API有频率限制的情况)

如果你的网站数量较多,或者PageSpeed API的配额有限,建议用串行方式,避免触发限流错误。

用async-await + for...of(推荐)

async function runSerialChecks() {
  // 假设websites是你的目标网站数组,比如:const websites = ["example.com", "test.com", ...];
  for (const site of websites) {
    try {
      const result = await pageSpeedCall(site);
      // 解析结果并处理,比如存到数组或打印
      const parsedResult = JSON.parse(result);
      console.log(`✅ 完成 ${site} 的检测:`, parsedResult);
      
      // 如果需要避免触发API限流,可以加个延迟
      // await new Promise(resolve => setTimeout(resolve, 1000));
    } catch (err) {
      console.error(`❌ 检测 ${site} 失败:`, err);
    }
  }
}

// 启动检测
runSerialChecks();

用传统回调+递归(适合不想用Promise的场景)

function runSerialWithCallbacks(index = 0) {
  if (index >= websites.length) {
    console.log("🎉 所有网站检测完成!");
    return;
  }
  
  const currentSite = websites[index];
  PageSpeedCall(currentSite, (err, result) => {
    if (err) {
      console.error(`❌ ${currentSite} 检测失败:`, err);
    } else {
      const parsedResult = JSON.parse(result);
      console.log(`✅ ${currentSite} 检测结果:`, parsedResult);
    }
    // 递归调用,处理下一个网站
    runSerialWithCallbacks(index + 1);
  });
}

// 启动检测
runSerialWithCallbacks();

方案2:并行调用(同时发起所有请求,速度更快)

如果网站数量不多,且API允许并发请求,可以用并行方式,效率更高:

async function runParallelChecks() {
  // 为每个网站创建一个检测Promise
  const checkPromises = websites.map(site => {
    return pageSpeedCall(site)
      .then(result => ({ site, data: JSON.parse(result) }))
      .catch(err => ({ site, error: err }));
  });
  
  // 等待所有请求完成
  const allResults = await Promise.all(checkPromises);
  
  // 遍历处理所有结果
  allResults.forEach(item => {
    if (item.error) {
      console.error(`❌ ${item.site} 检测失败:`, item.error);
    } else {
      console.log(`✅ ${item.site} 检测结果:`, item.data);
    }
  });
}

// 启动检测
runParallelChecks();

重要提醒

  • API限流问题:PageSpeed API有请求配额限制,并行调用过多可能会返回429错误,这种情况下优先选择串行并添加适当延迟
  • 错误处理:一定要保留错误处理逻辑,避免某个网站检测失败导致整个流程卡住
  • 参数校验:可以在函数里加个简单的参数校验,确保传入的site是有效的域名

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:41:45