前言
答案提供了关于在使用任何 Google 服务(内置和高级)或 API 时可能遇到的一般错误的指南。有关特定服务的错误,请参阅the other answer。
Back to reference
一般错误
留言
TypeError:无法从undefined (or null) 读取属性“property name here”
说明
错误消息表明您正在尝试访问 Object 实例上的属性,但在运行时期间,变量持有的值实际上是特殊数据输入undefined。通常,在访问对象的嵌套属性时会发生错误。
使用数值代替属性名称的此错误的变体表示应有 Array 的实例。由于 JavaScript 中的数组是 objects,所以这里提到的所有关于它们的内容都是正确的。
动态构造对象有一种特殊情况,例如 event objects,它们仅在特定上下文中可用,例如向应用发出 HTTP 请求或通过时间或基于事件的触发器调用函数.
错误是TypeError,因为应该是"object",但收到了"undefined"
如何解决
-
使用默认值
JavaScript 中的Logical OR || 运算符有一个有趣的属性,即如果左侧是falsy,则计算右侧。由于 JS 中的对象是真实的,而 undefined 和 null 是虚假的,所以像 (myVar || {}).myProp [(myVar || [])[index] for arrays] 这样的表达式将保证不会抛出错误,并且属性至少是 undefined。
也可以提供默认值:(myVar || { myProp : 2 })保证访问myProp默认返回2。数组也是如此:(myVar || [1,2,3])。
-
检查类型
对于特殊情况尤其如此,typeof operator 结合 if statement 和 comparison operator 将允许函数在其指定上下文之外运行(即用于调试目的)或引入分支逻辑,具体取决于关于对象是否存在。
可以控制检查的严格程度:
- 松懈(“未定义”):
if(typeof myVar !== "undefined") { //do something; }
- 严格(“仅限正确的对象”):
if(typeof myVar === "object" && myVar) { //do stuff }
相关问答
-
GAS 项目的Parsing order 是问题的根源
留言
无法将some value 转换为data type
说明
由于传递的参数与方法预期的不同类型而引发错误。导致错误的常见错误是number to string 的意外强制。
如何重现
function testConversionError() {
const ss = SpreadsheetApp.getActiveSheet();
ss.getRange("42.0",1);
}
如何解决
确保错误消息中引用的值是文档要求的数据类型,并根据需要确保convert。
留言
无法从此上下文调用Service and method name
说明
此错误发生在 上下文不匹配 上,并且特定于 container-bound 脚本。
导致错误的主要用例是尝试从另一个(即 @987654401 @来自电子表格)。
次要但也是突出的情况是调用服务not explicitly allowed 以从自定义函数(通常是由特殊JSDoc 样式注释@customfunction 标记并使用的函数)的结果作为公式)。
如何重现
对于绑定脚本上下文不匹配,在绑定到 Google 表格(或除 Google 文档之外的任何内容)的脚本项目中声明并运行此函数:
function testContextMismatch() {
const doc = DocumentApp.getUi();
}
请注意,调用DocumentApp.getActiveDocument() 只会导致null 不匹配,并且执行会成功。
对于自定义函数,使用下面在任何单元格中声明的函数作为公式:
/**
* @customfunction
*/
function testConversionError() {
const ui = SpreadsheetApp.getUi();
ui.alert(`UI is out of scope of custom function`);
}
如何解决
- 通过更改调用该方法的服务可以轻松解决上下文不匹配问题。
- 自定义函数无法调用这些服务,请使用custom menus or dialogs。
留言
找不到方法Method name here
参数param names 与method name 的方法签名不匹配
说明
这个错误对于新手来说是出了名的令人困惑的信息。它说的是在调用相关方法时传递的一个或多个参数中发生了类型不匹配。
signature 没有与您的调用方式相对应的方法,因此“未找到”
如何解决
这里唯一的解决方法是仔细阅读文档并检查参数的顺序和inferred type 是否正确(使用具有自动完成功能的良好 IDE 会有所帮助)。但是,有时会发生问题,因为人们期望值是某种类型,而在 runtime 它是另一种类型。有几个技巧可以防止此类问题:
- 设置类型保护(
typeof myVar === "string" 和类似的)。
- 由于 JavaScript 为 dynamically typed,因此添加了一个验证器来动态修复类型。
示例
/**
* @summary pure arg validator boilerplate
* @param {function (any) : any}
* @param {...any} args
* @returns {any[]}
*/
const validate = (guard, ...args) => args.map(guard);
const functionWithValidator = (...args) => {
const guard = (arg) => typeof arg !== "number" ? parseInt(arg) : arg;
const [a,b,c] = validate(guard, ...args);
const asObject = { a, b, c };
console.log(asObject);
return asObject;
};
//driver IIFE
(() => {
functionWithValidator("1 apple",2,"0x5");
})()
消息
您无权执行该操作
脚本无权执行该操作
说明
该错误表明访问的 API 或服务之一缺乏来自用户的足够权限。在其文档中包含 authorization 部分的每个服务方法都需要至少一个要授权的范围。
由于 GAS 本质上为方便开发而封装了 Google API,因此 OAuth 2.0 中列出的 API 范围 reference 中的大部分范围都可以使用,但如果在相应的文档中列出了其中的一个,那么使用它可能会更好有一些不一致的地方。
请注意,自定义函数在未经授权的情况下运行。从 Google 表格单元格调用函数是导致此错误的最常见原因。
如何解决
如果从脚本编辑器运行调用服务的函数,系统会自动提示您使用相关范围对其进行授权。尽管对于快速手动测试很有用,但最好在应用程序清单 (appscript.json) 中使用 set scopes explicitly。此外,如果打算发布应用程序,自动范围通常太宽而无法通过review。
清单文件中的字段oauthScopes(如果在代码编辑器中则为View -> Show manifest file)应如下所示:
"oauthScopes": [
"https://www.googleapis.com/auth/script.container.ui",
"https://www.googleapis.com/auth/userinfo.email",
//etc
]
对于自定义函数,您可以通过切换到从菜单或按钮as custom functions cannot be authorized调用函数来修复它。
对于开发editor Add-ons 的开发人员,此错误意味着未处理的authorization lifecycle 模式:如果身份验证模式为AuthMode.NONE,则必须在调用需要授权的服务之前中止。
相关原因及解决办法
-
@OnlyCurrentDoclimiting script access范围
- 范围autodetection
留言
ReferenceError: service name 未定义
说明
最常见的原因是使用 advanced service 而不启用它。启用此类服务后,指定标识符下的变量将附加到global scope,开发人员可以直接引用该变量。因此,当引用禁用的服务时,会抛出 ReferenceError。
如何解决
转到“资源 -> 高级 Google 服务”菜单并启用引用的服务。请注意,标识符应等于引用的全局变量。
更详细的解释请阅读official guide。
如果没有引用任何高级服务,则错误指向一个未声明的变量被引用。
留言
脚本完成但没有返回任何内容。
找不到脚本函数:doGet or doPost
说明
这本身不是错误(因为返回的 HTTP 响应代码是 200 并且执行被标记为成功,但通常被认为是成功。尝试从浏览器发出请求/访问时出现该消息 a脚本deployed as a Web App.
发生这种情况的主要原因有两个:
- 没有
doGet或doPost触发函数
- 上面的触发器不返回
HtmlOutput 或TextOutput 实例
如何解决
对于第一个原因,只需提供 doGet 或 doPost 触发器(或两者)函数。其次,确保您的应用程序的所有路由都以 TextOutput 或 HtmlOutput 的创建结束:
//doGet returning HTML
function doGet(e) {
return HtmlService.createHtmlOutput("<p>Some text</p>");
}
//doPost returning text
function doPost(e) {
const { parameters } = e;
const echoed = JSON.stringify(parameters);
return ContentService.createTextOutput(echoed);
}
请注意,应该只声明一个触发函数 - 将它们视为应用程序的入口点。
如果触发器依赖parameter / parameters 来路由响应,请确保请求 URL 的结构为“baseURL/exec?query”或“baseURL/dev?query " 其中query 包含parameters to pass。
相关问答
-
Redeploying 声明触发器后
留言
很抱歉,发生服务器错误。请稍等,然后重试。
说明
这是最神秘的错误,几乎可以在任何服务的任何时候发生(尽管DriveApp 的使用特别容易受到它的影响)。该错误通常表明 Google 方面的问题在几个小时/几天内消失或在此过程中得到修复。
如何解决
没有灵丹妙药,通常,除了问题跟踪器上的filing an issue 或contacting support(如果您有 GSuite 帐户)之外,您无能为力。在这样做之前,可以尝试以下常见的补救措施:
- 对于 bound 脚本 - 创建新文档并复制现有项目和数据。
- 切换到使用高级
Drive service(始终记得先启用它)。
- 如果错误指向带有 1 的行,则可能会有 problem with a regular expression。
不要对这个错误大发雷霆 - 尝试找到受影响的代码、文件或为问题加注星标,然后继续
没有明显问题的语法错误
此错误可能是由于在使用已弃用的 V8 运行时(在编写 GAS 平台时uses V8 时)使用 ES6 语法(例如箭头函数)引起的。
如何解决
打开“appscript.json”清单文件并检查runtimeVersion是否设置为"V8",如果不是则更改,否则删除任何ES6 features。
配额相关错误
有几个与对服务使用的配额有关的错误。 Google 有其中的 comprehensive list,但根据一般经验法则,如果邮件与 “too many” 模式匹配,则您可能已超出相应的配额。
最可能遇到的错误:
- 服务调用次数过多:
service name
- 运行的脚本太多
- 一天使用过多计算机时间的服务
- 此脚本的触发器过多
如何解决
在大多数情况下,唯一的解决方法是等到配额刷新或切换到另一个帐户(除非脚本部署为具有“以我身份运行”权限的 Web 应用程序,在这种情况下 所有者的 配额将在所有用户之间共享)。
要引用当时的文档:
每日配额在 24 小时窗口结束时刷新;但是,此刷新的确切时间因用户而异。
请注意,MailApp 等某些服务具有getRemainingDailyQuota 等可以检查剩余配额的方法。
在超过最大触发器数量的情况下,可以通过getProjectTriggers()(或检查"My triggers"选项卡)检查安装了多少触发器并采取相应措施减少数量(例如,通过使用deleteTrigger(trigger)来获取去掉一些)。
相关规范问答
-
How are daily 限制正在应用和刷新?
- “超过最大执行时间”problem
-
Optimizing service calls 减少执行时间
参考文献
- 如何出错messages more meaningful
- 调试custom functions