sbi*_*biz 5 google-apps-script google-app-maker
我正在开发App Maker应用程序,并从客户端脚本中调用服务器端函数(假设函数a
和函数b
),它们相互依赖。
客户端脚本中的第一个(本机)解决方案如下,该解决方案使用回调:
function doB(s) {
google.script.run.withSuccessHandler(function(result) { // async workload
console.log(result);
}).withFailureHandler(function(error) {
console.log(error);
}).b(s);
}
function aThenB(s) {
google.script.run.withSuccessHandler(function(result) { // async workload
console.log(result);
doB(result); // call b
}).withFailureHandler(function(error) {
console.log(error);
}).a(s);
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您必须先调用function c
,然后再调用d
等等,并获得这些相关函数的执行结果,这将变得非常笨拙。我阅读了这篇文章,其中描述了从回调到Promise的转换,例如:
function runnerToPromise(f) {
var runArgs = Array.prototype.slice.call(arguments).slice(1);
return new Promise(function(resolve, reject) { // executor
google.script.run.withSuccessHandler(function(result) {
resolve(result); // resolve promise
}).withFailureHandler(function(error) {
reject(error); // reject promise
})[f].apply(this, runArgs); // async
});
}
Run Code Online (Sandbox Code Playgroud)
这将使上面的代码看起来像:
function aThenB(s) {
return runnerToPromise('a', s).then(
function(result) {
return runnerToPromise('b', result);
}
);
}
function runAThenB(s) {
aThenB(s).then(function(result) {
console.log('SUCCESS: ' + result);
}).catch(function(error) {
console.log(error);
});
}
Run Code Online (Sandbox Code Playgroud)
如果您使用Apps Script和HtmlService
,并且将该脚本部署为“ Web App”,则此解决方案将正常工作。
但是,在App Maker中,它引发了一个我无法理解的错误:
TypeError:无法读取未定义的属性'withLogger'。
如何解决此仅适用于App Maker的错误?
我使用App Maker制作了一个新的测试应用,以重现该问题。
该应用程序就是这样做的:分两个步骤将数据从一个电子表格复制到另一个电子表格。
我在App Maker中运行代码,并且还将代码部署为使用Apps Script制作的Web应用程序。
使用Apps脚本制作的Web应用程序没有问题;在App Maker中,只有使用回调的解决方案才能正常工作。
服务器端脚本:
function serverStepOne() {
console.log('serverStepOne fn called!');
return SpreadsheetApp
.openById('XXX') // Spreadsheet A
.getSheetByName('A')
.getDataRange()
.getValues();
}
function serverStepTwo(grid) {
console.log('serverStepTwo fn called!');
SpreadsheetApp
.openById('YYY') // Spreadsheet B
.getSheetByName('A').getRange(1, 1, grid.length, grid[0].length).setValues(grid); // all rows have the same number of cells
return 'copy done!';
}
Run Code Online (Sandbox Code Playgroud)
客户端脚本:
function copyData() { // messy one... works like a charm in App Maker
google.script.run.withSuccessHandler(function(result) {
google.script.run.withSuccessHandler(function(result) {console.log(result);}).withFailureHandler(function(error) {console.log(error);}).serverStepTwo(result);
}).withFailureHandler(function(error) {console.log(error);}).serverStepOne();
}
function runnerToPromise(f) {
var runArgs = Array.prototype.slice.call(arguments).slice(1);
return new Promise(function(resolve, reject) {
google.script.run.withSuccessHandler(function(result) {
resolve(result);
}).withFailureHandler(function(error) {
reject(error);
})[f].apply(this, runArgs);
});
}
function copyDataPromise() { // tidy one... doesn't work in App Maker; works in Apps Script Web App
return runnerToPromise('serverStepOne').then(
function(result) {
return runnerToPromise('serverStepTwo', result);
});
}
function runCopyDataPromise() {
copyDataPromise().then(function(result) {console.log(result);}).catch(function(error) {console.log(error);});
}
Run Code Online (Sandbox Code Playgroud)
调用copyDataPromise fn时,App Maker在浏览器的控制台中生成以下日志:
com.google.apps.appmaker.AppMakerGwt-0.js:7706 Uncaught (in promise) TypeError: Cannot read property 'withLogger' of undefined
at n.(n-omfqufplv3inu3qxlfsar7h6wn2rogznri3mjoq-0lu-script.googleusercontent.com/anonymous function) (com.google.apps.appmaker.AppMakerGwt-0.js:7706:182)
at clientScriptsContext.js:14
at <anonymous>:26:11
at new Promise (<anonymous>)
at runnerToPromise (<anonymous>:16:10)
at copyDataPromise (<anonymous>:32:10)
at COMPONENT_EVENT_1sVF9N7aiAUX2sXc4qZ90Ben2JowEfeez_0_1142335744_onClick (<anonymous>:48:1)
at window.am_exit (clientScriptsContext.js:22)
at UZ (com.google.apps.appmaker.AppMakerGwt-0.js:6651)
at LZ (com.google.apps.appmaker.AppMakerGwt-0.js:4950)
at NZ (com.google.apps.appmaker.AppMakerGwt-0.js:6043)
at Qgb (com.google.apps.appmaker.AppMakerGwt-0.js:6803)
at QTb.RTb [as sc] (com.google.apps.appmaker.AppMakerGwt-0.js:7738)
at ozd.pzd [as xd] (com.google.apps.appmaker.AppMakerGwt-0.js:7746)
at wCd (com.google.apps.appmaker.AppMakerGwt-0.js:7328)
at oCd (com.google.apps.appmaker.AppMakerGwt-0.js:6718)
at Id (com.google.apps.appmaker.AppMakerGwt-0.js:1394)
at Wyd (com.google.apps.appmaker.AppMakerGwt-0.js:6732)
at Kd (com.google.apps.appmaker.AppMakerGwt-0.js:6025)
at PHc.Vd [as dc] (com.google.apps.appmaker.AppMakerGwt-0.js:7728)
at pue (com.google.apps.appmaker.AppMakerGwt-0.js:5477)
at HTMLButtonElement.Vve (com.google.apps.appmaker.AppMakerGwt-0.js:4828)
at Drd (com.google.apps.appmaker.AppMakerGwt-0.js:2887)
at Grd (com.google.apps.appmaker.AppMakerGwt-0.js:6717)
at HTMLButtonElement.eval (com.google.apps.appmaker.AppMakerGwt-0.js:4677)
n.(anonymous function) @ com.google.apps.appmaker.AppMakerGwt-0.js:7706
(anonymous) @ clientScriptsContext.js:14
(anonymous) @ VM28:26
runnerToPromise @ VM28:16
copyDataPromise @ VM28:32
COMPONENT_EVENT_1sVF9N7aiAUX2sXc4qZ90Ben2JowEfeez_0_1142335744_onClick @ VM38:48
window.am_exit @ clientScriptsContext.js:22
UZ @ com.google.apps.appmaker.AppMakerGwt-0.js:6651
LZ @ com.google.apps.appmaker.AppMakerGwt-0.js:4950
NZ @ com.google.apps.appmaker.AppMakerGwt-0.js:6043
Qgb @ com.google.apps.appmaker.AppMakerGwt-0.js:6803
RTb @ com.google.apps.appmaker.AppMakerGwt-0.js:7738
pzd @ com.google.apps.appmaker.AppMakerGwt-0.js:7746
wCd @ com.google.apps.appmaker.AppMakerGwt-0.js:7328
oCd @ com.google.apps.appmaker.AppMakerGwt-0.js:6718
Id @ com.google.apps.appmaker.AppMakerGwt-0.js:1394
Wyd @ com.google.apps.appmaker.AppMakerGwt-0.js:6732
Kd @ com.google.apps.appmaker.AppMakerGwt-0.js:6025
Vd @ com.google.apps.appmaker.AppMakerGwt-0.js:7728
pue @ com.google.apps.appmaker.AppMakerGwt-0.js:5477
Vve @ com.google.apps.appmaker.AppMakerGwt-0.js:4828
Drd @ com.google.apps.appmaker.AppMakerGwt-0.js:2887
Grd @ com.google.apps.appmaker.AppMakerGwt-0.js:6717
(anonymous) @ com.google.apps.appmaker.AppMakerGwt-0.js:4677
Promise.then (async)
copyDataPromise @ VM28:32
COMPONENT_EVENT_1sVF9N7aiAUX2sXc4qZ90Ben2JowEfeez_0_1142335744_onClick @ VM38:48
window.am_exit @ clientScriptsContext.js:22
UZ @ com.google.apps.appmaker.AppMakerGwt-0.js:6651
LZ @ com.google.apps.appmaker.AppMakerGwt-0.js:4950
NZ @ com.google.apps.appmaker.AppMakerGwt-0.js:6043
Qgb @ com.google.apps.appmaker.AppMakerGwt-0.js:6803
RTb @ com.google.apps.appmaker.AppMakerGwt-0.js:7738
pzd @ com.google.apps.appmaker.AppMakerGwt-0.js:7746
wCd @ com.google.apps.appmaker.AppMakerGwt-0.js:7328
oCd @ com.google.apps.appmaker.AppMakerGwt-0.js:6718
Id @ com.google.apps.appmaker.AppMakerGwt-0.js:1394
Wyd @ com.google.apps.appmaker.AppMakerGwt-0.js:6732
Kd @ com.google.apps.appmaker.AppMakerGwt-0.js:6025
Vd @ com.google.apps.appmaker.AppMakerGwt-0.js:7728
pue @ com.google.apps.appmaker.AppMakerGwt-0.js:5477
Vve @ com.google.apps.appmaker.AppMakerGwt-0.js:4828
Drd @ com.google.apps.appmaker.AppMakerGwt-0.js:2887
Grd @ com.google.apps.appmaker.AppMakerGwt-0.js:6717
(anonymous) @ com.google.apps.appmaker.AppMakerGwt-0.js:4677
Run Code Online (Sandbox Code Playgroud)
Stackdriver中完全没有错误。
我对代码做了一些修改,添加了命名函数表达式。
function runnerToPromise(f) {
var runArgs = Array.prototype.slice.call(arguments).slice(1);
return new Promise(function myExecutor(resolve, reject) {
google.script.run.withSuccessHandler(function myWithSuccessHandler(result) {
resolve(result);
}).withFailureHandler(function myWithFailureHandler( error) {
reject(error);
})[f].apply(null, runArgs);
});
}
function copyDataPromise() { // tidy one... doesn't work at all in App Maker; works with Apps Script (Web App)
return runnerToPromise('serverStepOne').then(
function myFirstPromiseThen(result) {
return runnerToPromise('serverStepTwo', result);
});
}
function runCopyDataPromise() {
copyDataPromise().then(function myLastPromiseThen(result) {console.log(result);}).catch(function myFinalCatch(error) {console.log(error);});
}
Run Code Online (Sandbox Code Playgroud)
控制台日志:
com.google.apps.appmaker.AppMakerGwt-0.js:formatted:57540 Uncaught (in promise) TypeError: Cannot read property 'withLogger' of undefined
at n.(n-omfqufplv3inu3qxlfsar7h6wn2rogznri3mjoq-0lu-script.googleusercontent.com/anonymous function) (com.google.apps.appmaker.AppMakerGwt-0.js:7706:182)
at clientScriptsContext.js:14
at myExecutor (<anonymous>:26:11)
at new Promise (<anonymous>)
at runnerToPromise (<anonymous>:16:10)
at copyDataPromise (<anonymous>:32:10)
at COMPONENT_EVENT_1sVF9N7aiAUX2sXc4qZ90Ben2JowEfeez_0_1142335744_onClick (<anonymous>:48:1)
at window.am_exit (clientScriptsContext.js:22)
at UZ (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36031)
at LZ (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:20165)
at NZ (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:29107)
at Qgb (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:38046)
at QTb.RTb [as sc] (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:77339)
at ozd.pzd [as xd] (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:93227)
at wCd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:46855)
at oCd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36933)
at Id (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:3853)
at Wyd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:37133)
at Kd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:28919)
at PHc.Vd [as dc] (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:61727)
at pue (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:23899)
at HTMLButtonElement.Vve (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:19342)
at Drd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:9567)
at Grd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36910)
at HTMLButtonElement.eval (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:18425)
n.(anonymous function) @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:57540
(anonymous) @ clientScriptsContext.js:14
myExecutor @ VM28:26
runnerToPromise @ VM28:16
copyDataPromise @ VM28:32
COMPONENT_EVENT_1sVF9N7aiAUX2sXc4qZ90Ben2JowEfeez_0_1142335744_onClick @ VM72:48
window.am_exit @ clientScriptsContext.js:22
UZ @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36031
LZ @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:20165
NZ @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:29107
Qgb @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:38046
RTb @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:77339
pzd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:93227
wCd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:46855
oCd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36933
Id @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:3853
Wyd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:37133
Kd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:28919
Vd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:61727
pue @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:23899
Vve @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:19342
Drd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:9567
Grd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36910
(anonymous) @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:18425
Promise.then (async)
copyDataPromise @ VM28:32
COMPONENT_EVENT_1sVF9N7aiAUX2sXc4qZ90Ben2JowEfeez_0_1142335744_onClick @ VM72:48
window.am_exit @ clientScriptsContext.js:22
UZ @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36031
LZ @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:20165
NZ @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:29107
Qgb @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:38046
RTb @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:77339
pzd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:93227
wCd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:46855
oCd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36933
Id @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:3853
Wyd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:37133
Kd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:28919
Vd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:61727
pue @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:23899
Vve @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:19342
Drd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:9567
Grd @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36910
(anonymous) @ com.google.apps.appmaker.AppMakerGwt-0.js:formatted:18425
Run Code Online (Sandbox Code Playgroud)
我试过下面的代码。它可以在Apps Script Web App中工作。它在App Maker中不起作用。在App Maker中,它引发相同的错误:无法读取未定义的属性'withLogger'
/*jshint esnext:true*/
const runnerToPromiseSpread = (fn, ...args) => {
return new Promise((resolve, reject) => {
let task = google.script.run
.withSuccessHandler(resolve)
.withFailureHandler(reject);
if (task[fn] === undefined) {
reject("'" + fn + "' is not a global function in your Apps Script project");
} else {
task[fn].apply(null, args);
}
});
};
function copyDataPromiseSpread() {
return runnerToPromiseSpread('serverStepOne')
.then((result) => {
return runnerToPromiseSpread('serverStepTwo', result);
});
}
function runCopyDataPromiseSpread() {
copyDataPromiseSpread().then((result) => {
console.log(result);
}).catch((error) => {
console.log(error);
});
}
Run Code Online (Sandbox Code Playgroud)
在浏览器的控制台中:
TypeError: Cannot read property 'withLogger' of undefined
at n.(n-omfqufplv3inu3qxlfsar7h6wn2rogznri3mjoq-0lu-script.googleusercontent.com/anonymous function) (com.google.apps.appmaker.AppMakerGwt-0.js:7706:182)
at clientScriptsContext.js:14
at <anonymous>:21:16
at new Promise (<anonymous>)
at runnerToPromiseSpread (<anonymous>:7:10)
at copyDataPromiseSpread (<anonymous>:28:10)
at runCopyDataPromiseSpread (<anonymous>:39:5)
at COMPONENT_EVENT_1sVF9N7aiAUX2sXc4qZ90Ben2JowEfeez_0_1142335744_onClick (<anonymous>:86:1)
at window.am_exit (clientScriptsContext.js:22)
at UZ (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36031)
at LZ (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:20165)
at NZ (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:29107)
at Qgb (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:38046)
at QTb.RTb [as sc] (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:77339)
at ozd.pzd [as xd] (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:93227)
at wCd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:46855)
at oCd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36933)
at Id (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:3853)
at Wyd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:37133)
at Kd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:28919)
at PHc.Vd [as dc] (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:61727)
at pue (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:23899)
at HTMLButtonElement.Vve (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:19342)
at Drd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:9567)
at Grd (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:36910)
at HTMLButtonElement.eval (com.google.apps.appmaker.AppMakerGwt-0.js:formatted:18425)
Run Code Online (Sandbox Code Playgroud)
@tehhowc h的评论非常有帮助:
此错误意味着对象任务运行程序(google.script.run 实例)已变得未定义。
确实,这就是appmaker内部的问题。为了解决这个问题,我简单地这样做了:
function runnerToPromise(f) {
var runArgs = Array.prototype.slice.call(arguments).slice(1);
return new Promise(function(resolve, reject) {
var runner = google.script.run.withSuccessHandler(function(result) {
resolve(result);
}).withFailureHandler(function(error) {
reject(error);
});
runner[f].apply(runner, runArgs);
});
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
445 次 |
最近记录: |