Вызов функции библиотеки из 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 еще может это исправить, поэтому я использую поднятый функции обратного вызова как настоящие оболочки на всякий случай.

Другие вопросы по тегам