在App Maker中运行google.script.run:TypeError:无法读取未定义的属性'withLogger'

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中完全没有错误。


更新2

我对代码做了一些修改,添加了命名函数表达式。

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)

图片1


更新3

我试过下面的代码。它可以在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)

Mor*_*smo 0

@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)