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

为何同一脚本可获取本人Nest温控器ID,他人使用却报错?

TypeError: Cannot read properties of undefined (reading 'forEach') 错误分析与修复

问题背景

我编写了一个包含listDevices函数的脚本用于获取Nest温控器ID,该脚本在我的Nest设备上运行正常,但当另一拥有多台Nest温控器的用户使用时,出现错误:TypeError: Cannot read properties of undefined (reading 'forEach')。以下是相关代码:

相关代码

listDevices函数

function listDevices() {

  // specify the endpoint
  const endpoint = '/enterprises/' + PROJECT_ID + '/devices';

  // blank array to hold device data
  let deviceArray = [];

  // make request to smart api
  const data = makeRequest(endpoint);
  const deviceData = data.devices;
  console.log(deviceData);

  deviceData.forEach(device => {
    const name = device.name;
    const type = device.type;
    deviceArray.push([name,type]);
  });

  // get the Sheet
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getActiveSheet();

  // output the data
  sheet.getRange(2,1,deviceArray.length,2).setValues(deviceArray);

}

makeRequest函数

function makeRequest(endpoint) {

  // get the smart service
  const smartService = getSmartService();
   
  // get the access token
  const access_token = smartService.getAccessToken();
  //console.log(access_token);

  // setup the SMD API url
  const url = 'https://smartdevicemanagement.googleapis.com/v1';
  //const endpoint = '/enterprises/' + PROJECT_ID + '/devices';

  // setup the headers for the call
  const headers = {
    'Authorization': 'Bearer ' + access_token,
    'Content-Type': 'application/json'
  }
   
  // set up params
  const params = {
    'headers': headers,
    'method': 'get',
    'muteHttpExceptions': true
  }
   
  // try calling API
  try {
    const response = UrlFetchApp.fetch(url + endpoint, params);
    const responseBody = JSON.parse(response.getContentText());
     
    return responseBody;
  }
  catch(e) {
    console.log('Error: ' + e);
  }
}

错误原因分析

报错直接指向deviceData.forEach这一行,说明deviceData为undefined,即data.devices不存在。核心原因如下:

  • API错误响应未处理:makeRequest中设置了muteHttpExceptions: true,即使API返回401(权限无效)、403(无访问权限)等错误状态码,也不会抛出异常,而是返回包含错误信息的响应体(无devices字段),此时data.devices自然为undefined。
  • 异常场景无返回值:makeRequest的catch块仅打印错误但未返回任何值,若出现JSON解析失败等异常,函数会返回undefined,后续访问data.devices也会触发错误。
  • 权限或配置问题:多设备用户可能未正确授权项目访问其所有设备,或使用了错误的PROJECT_ID,导致API返回无设备数据的响应。

修复方案

1. 增加数据合法性校验

在listDevices中先校验数据有效性,避免直接调用forEach:

function listDevices() {
  const endpoint = '/enterprises/' + PROJECT_ID + '/devices';
  let deviceArray = [];

  const data = makeRequest(endpoint);
  // 可选链+数组类型校验,避免undefined报错
  const deviceData = data?.devices;
  if (Array.isArray(deviceData)) {
    deviceData.forEach(device => {
      const name = device.name;
      const type = device.type;
      deviceArray.push([name, type]);
    });
  } else {
    console.log("获取设备数据失败,响应内容:", data);
    // 给用户直观提示
    const ss = SpreadsheetApp.getActiveSpreadsheet();
    const sheet = ss.getActiveSheet();
    sheet.getRange(2,1).setValue("获取设备数据失败,请检查权限或项目配置");
    return;
  }

  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getActiveSheet();
  sheet.getRange(2,1,deviceArray.length,2).setValues(deviceArray);
}

2. 完善API错误处理

在makeRequest中检查响应状态码,明确区分成功与失败场景:

function makeRequest(endpoint) {
  const smartService = getSmartService();
  const access_token = smartService.getAccessToken();
  const url = 'https://smartdevicemanagement.googleapis.com/v1';

  const headers = {
    'Authorization': 'Bearer ' + access_token,
    'Content-Type': 'application/json'
  };

  const params = {
    'headers': headers,
    'method': 'get',
    'muteHttpExceptions': true
  };

  try {
    const response = UrlFetchApp.fetch(url + endpoint, params);
    const statusCode = response.getResponseCode();
    // 仅处理200系列成功响应
    if (statusCode >= 200 && statusCode < 300) {
      const responseBody = JSON.parse(response.getContentText());
      return responseBody;
    } else {
      const errorBody = JSON.parse(response.getContentText());
      console.log(`API请求失败,状态码: ${statusCode},错误信息:`, errorBody);
      return { error: errorBody.error };
    }
  } catch(e) {
    console.log('请求或解析错误: ' + e);
    return { error: e.message };
  }
}

3. 确认用户配置与权限

  • 确保多设备用户使用自己的PROJECT_ID,而非你的项目ID;
  • 指导用户重新授权应用,确保授权范围覆盖所有Nest设备;
  • 检查用户的Google Cloud项目是否已启用Smart Device Management API。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:30:49