Вызов функции библиотеки из html с google.script.run
Я реализую библиотеку с помощью Google App Script, и у меня возникают трудности с вызовом функции из библиотеки с помощью google.script.run.
Вот код моей библиотеки:
Code.gs
function ShowSideBar() {
var html = HtmlService.createTemplateFromFile('Index_librairie').evaluate()
.setTitle('Console de gestion')
.setWidth(300);
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showSidebar(html);
}
function execution_appeler_par_html(){
Logger.log("execution_appeler_par_html");
}
Index_librairie.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
google.script.run.withSuccessHandler(work_off).execution_appeler_par_html();
function work_off(e){
alert(e);
}
</script>
</head>
<body>
test de ouf
</body>
</html>
Вот моя электронная таблица, в которой используется библиотека: Code.gs
function onopen() {
lbrairietestedouard.ShowSideBar();
}
Google.script.run не восстанавливает функцию execute_appeler_par_html(). Я должен использовать libraryname.execution_appeler_par_html(), но этот синтаксис не работает в конфигурации google.script.run
5 ответов
Похоже, что google.script.run не может заглянуть внутрь объектов или самостоятельно выполняемых анонимных функций. В моем случае размещение любого кода внутри объекта или IIFE приводило к ошибке типа "не функция", возникающей в консоли.
Вы можете обойти это, объявив одну функцию, которая будет вызывать вложенные методы внутри библиотек и объектов.
Файл.GS
function callLibraryFunction(func, args){
var arr = func.split(".");
var libName = arr[0];
var libFunc = arr[1];
args = args || [];
return this[libName][libFunc].apply(this, args);
}
В JavaScript каждый объект ведет себя как ассоциативный массив пар ключ-значение, включая глобальный объект, на который "this" будет указывать в этом сценарии. Хотя и libName, и libFunc имеют тип String, мы все равно можем ссылаться на них внутри глобального объекта, используя приведенный выше синтаксис. apply() просто вызывает функцию 'this', делая результат доступным в глобальной области видимости.
Вот как вы вызываете библиотечную функцию из клиента:
google.script.run.callLibraryFunction("Library.libraryFunction", [5, 3]);
Я не претендую на это решение как на мое собственное - это то, что я видел на сайте Брюса МакФерсона некоторое время назад. Вы могли бы предложить другие специальные решения, которые могут быть более подходящими для вашего случая, но я думаю, что это наиболее универсальное решение.
Заметил ту же проблему при попытке вызвать библиотеку из google.script.run в HTML-коде. Вот обходной путь, который я использую:
БИБЛИОТЕКА: aLibrary
function aFunction(){
//code...;
}
ADDON SIDE (требуется библиотека "aLibrary")
function aFunction(){
aLibrary.aFunction();
}
HTML
<input type="button" value="run aFunction" onclick="google.script.run.aFunction()" />
Мне нравится обходной путь, потому что я сохраняю четкое представление и организацию имен своих функций, и мне не нужно изменять HTML-код, если я добавлю свои функции непосредственно в проект надстройки, как только разработка будет удовлетворительной.
Единственное, что я еще не пробовал: обработка аргументов и возвращаемых значений....
Я надеюсь, что этот вклад не глупый, пожалуйста, простите меня, я очень любитель...
После довольно долгой работы над этим я обнаружил, что любая функция, которую вы вызываете из библиотеки, используя
google.script.run
должен существовать как в основном скрипте, так и в библиотечном скрипте. Функция должна быть как минимум объявлена в основном скрипте, а реализация и параметры не важны. Реализация будет в вашей библиотеке. Если основной скрипт не включает имя функции, ошибка
<your function> is not a function
появится.
Теперь, когда нет смысла иметь библиотеку, если каждая отдельная функция должна существовать в основной функции, решение, предоставленное @Anton Dementiev, будет использоваться в качестве обходного пути. Предположим, у вас есть функция с именем
testFunc
в вашей библиотеке вы можете вызвать его, используя следующий метод:
google.script.run.callLibraryFunction("testFunc", [5, 3]);
где библиотека имеет эту функцию:
function callLibraryFunction(func, args) {
args = args || [];
return this[func].apply(this, args);
}
и основной скрипт имеет это объявление:
function callLibraryFunctdion() {
}
Google должен исправить это глупое поведение
У меня есть аналогичная проблема, с которой меня недавно направили в эту тему, и я попробовал множество решений... однако вчера я наткнулся на другую тему (которую я, к сожалению, щелкнул или потерял из виду, поэтому не могу ссылаться на нее ), в котором предлагалось решение другой проблемы, с которой я столкнулся с библиотеками.
Angelo в этой теме на самом деле очень близок к тому, что, как я нашел, сработало для меня, поэтому, пожалуйста, обратитесь к его ответу с одним небольшим изменением на стороне клиента/надстройки:
Для меня просто добавление «возврата» — это то, что помогло. Это было чрезвычайно простое решение (намного более простое, чем многие другие предлагаемые варианты), поэтому я подумал, что будет полезно поделиться им со всеми, кто находится в моей лодке. Возможно, это сработает не для всех (я еще не тестировал его полностью), но оно изменило мои «нулевые» значения на ожидаемые значения массива, которые я хотел, поэтому я доволен этим для своих простых/любительских нужд. Не уверен, что он будет работать с аргументами, но, по крайней мере, для простых функций без аргументов он выполняет свою работу.
Обновление: я только что проверил это с помощью простого аргумента.array
где я обновил обе стороны Lib/Client, чтобы принять аргумент, установил переменную в html-скрипте на стороне клиента равнымvar testArray = ['opt 1', 'opt 2', 'opt 3']
и передал его в функцию через html-скрипт - отлично работал в обоих направлениях и выходил на другую сторону в моем выводе html/JavaScript. Поэтому я могу подтвердить, что на данный момент это должно работать даже для функций с простыми аргументами.
Насколько я могу судить, проблема связана с подъемом — см. этот ответ здесь.
Разница в том, что functionOne является выражением функции и поэтому определяется только при достижении этой строки, тогда как functionTwo является объявлением функции и определяется, как только выполняется окружающая его функция или скрипт (из-за подъема).
Очевидно,google.script.run
выполняется на уровне, предшествующем любому объявлению переменных в зависимых скриптах. Так что да, при использовании обратных вызовов формыgoogle.script.run.myWhateverCallback()
в библиотеке зависимые сценарии должны определять этот обратный вызов как поднимаемую функцию, а не в объявлении переменной/константы.
/* don't do this, as you might for your controller actions in the app menu */
const { myWhateverCallback, myOtherCallback } = MyParentLibrary;
/* do this instead, for *every* callback needed by google.script.run */
function myWhateverCallback()
MyParentLibrary.myWhateverCallback(...arguments);
}
Согласно предыдущим ответам, тело функции может быть избыточным, поскольку окончательное выполнение функции находится в области родительской библиотеки , но я не проверял это, и Google еще может это исправить, поэтому я использую поднятый функции обратного вызова как настоящие оболочки на всякий случай.