Google Apps Script调用Slack users.profile.get触发限流返回200如何解决?
问题原因与解决方案
1. 状态码与限流标识不符的问题
Slack 部分API端点的限流响应存在实现特例,不会严格返回429状态码,而是返回200状态码同时在响应体中返回ok: false和ratelimited错误,你不需要依赖getResponseCode()的结果,直接判断响应体的ok字段和error字段即可判断是否触发限流。
2. 规避限流的实现方案
不要用固定时长的Utilities.sleep(),改用指数退避重试逻辑适配自定义限流规则,同时优化表格读写逻辑减少不必要的耗时,避免请求发送过于集中。
优化后的完整代码:
// 配置参数 const MAX_RETRY = 3; // 最大重试次数 const RETRY_BASE_DELAY = 1000; // 重试基础等待时长,单位毫秒 const FIELD_ID = "你的自定义字段ID"; // 替换为实际的FieldID // 先把所有用户数据存到数组里,最后批量写入表格,大幅减少IO耗时 const outputData = []; for (var i = 0; i < userslist.length; i++) { const user = userslist[i]; const row = [ user.id, user.deleted, user.real_name, user.profile?.title || "", user.profile?.phone || "", user.profile?.skype || "", "" // 第7列留着存自定义字段值 ]; const citypayload = { "token": token, "user": user.id, "include_labels": true }; let cityData; let retryCount = 0; let requestSuccess = false; // 指数退避重试逻辑 while (retryCount < MAX_RETRY && !requestSuccess) { try { const response = UrlFetchApp.fetch( "https://slack.com/api/users.profile.get", { "method": "get", "payload": citypayload } ); cityData = JSON.parse(response.getContentText()); // 判断是否触发限流 if (!cityData.ok && cityData.error === 'ratelimited') { retryCount++; const delay = RETRY_BASE_DELAY * Math.pow(2, retryCount); Utilities.sleep(delay); continue; } requestSuccess = true; } catch (e) { // 处理网络异常,也触发重试 retryCount++; const delay = RETRY_BASE_DELAY * Math.pow(2, retryCount); Utilities.sleep(delay); } } // 读取自定义字段值 if (requestSuccess && cityData.profile?.fields?.[FIELD_ID]) { row[6] = cityData.profile.fields[FIELD_ID].value; } outputData.push(row); console.log(cityData); } // 批量写入表格,只调用一次写接口 sheet.getRange(1, 1, outputData.length, 7).setValues(outputData);
3. 核心优化点说明
- 指数退避重试:根据重试次数动态调整等待时长,比固定时长sleep适配性更强,不会浪费时间也不会因为等待时长不够触发二次限流,仅在触发限流时才执行等待,不会无意义拖慢整体请求速度
- 批量表格写入:把循环内的多次
setValue合并为单次setValues,可以减少90%以上的表格IO耗时,脚本整体运行速度提升明显 - 修复语法错误:原代码中
cityData.profile.fields."FieldID".value属于非法语法,改为用方括号取值cityData.profile.fields[FIELD_ID].value - 可选值兼容:用可选链
?.避免字段不存在时报错,不需要额外的try-catch包裹
内容的提问来源于stack exchange,提问作者Scotobaza
相关产品推荐
相关产品推荐

