خدمة HTML: التواصل مع دوال الخادم

google.script.run غير متزامن واجهة برمجة تطبيقات JavaScript من جهة العميل تسمح لصفحات خدمة HTML بطلب البيانات من جهة الخادم وظائف "برمجة تطبيقات Google". يوضح المثال التالي الوظائف الأساسية من google.script.runاستدعاء دالة على الخادم من JavaScript من جهة العميل.

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function doSomething() {
  Logger.log('I was called!');
}

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      google.script.run.doSomething();
    </script>
  </head>
</html>

إذا نشرت هذا النص البرمجي كتطبيق ويب وزرت عنوان URL الخاص به، لن ترى أي شيء، ولكن إذا عرضت السجلات، فسترى أن الخادم يعمل تم الاتصال بـ "doSomething()".

تكون الطلبات من جهة العميل للدوال من جهة الخادم غير متزامنة: بعد فتح المتصفّح. أن يشغّل الخادم الدالة doSomething()، سيستمر المتصفّح مباشرةً إلى السطر التالي من التعليمة البرمجية دون انتظار الرد. يعني ذلك قد لا يتم تنفيذ استدعاءات دالة الخادم بالترتيب الذي تتوقعه. إذا أجريت اثنين من استدعاءات الدوال في نفس الوقت، فلا توجد طريقة لمعرفة الدالة التي التشغيل أولاً؛ فقد تختلف النتيجة في كل مرة تقوم فيها بتحميل الصفحة. في هذه الحالة، معالِجات النجاح ومعالِجات الإخفاق للمساعدة في التحكم في تدفق التعليمات البرمجية.

تسمح واجهة برمجة التطبيقات google.script.run بإجراء 10 طلبات متزامنة لوظائف الخادم. في حال حذف تجري الاتصال الحادي عشر بينما لا تزال الرقم 10 قيد التشغيل، فإن دالة الخادم ستكون متأخرًا حتى يتم تحرير أحد الأماكن العشرة. من الناحية العملية، نادرًا ما يكون لديك للتفكير في هذا القيد، خاصةً وأن معظم المتصفحات تضع حدودًا عدد الطلبات المتزامنة إلى نفس الخادم برقم أقل من 10. في Firefox، على سبيل المثال، الحد الأقصى هو 6. تؤدي معظم المتصفحات إلى تأخير زيادة الوقت إلى أن يكتمل أحد الطلبات الحالية.

المَعلمات والقيم المعروضة

يمكنك استدعاء دالة خادم تضم معلمات من العميل. وبالمثل، على إرجاع قيمة إلى العميل كمعلمة تم تمريرها إلى معالج النجاح.

المعلمات القانونية والقيم المعروضة هي قواعد أساسية لـ JavaScript مثل Number Boolean أو String أو null، بالإضافة إلى كائنات JavaScript والصفائف التي تتألف من الوحدات الأساسية والكائنات والصفيفات. عنصر form في الصفحة هي أيضًا قانونية كمعلمة، ولكن يجب أن تكون هي المعلمة الوحيدة للدالة، إلا أنها لا تُعتبر قانونية كقيمة معروضة. تخفق الطلبات إذا حاولت اجتياز Date أو Function أو DOM إلى جانب form أو أي نوع آخر محظور بما في ذلك الأنواع المحظورة داخل الكائنات أو الصفائف. الكائنات التي تنشئ ستفشل المراجع الدائرية أيضًا، وتصبح الحقول غير المحددة داخل الصفائف null

لاحظ أن العنصر الذي يتم تمريره إلى الخادم يصبح نسخة من الأصل. إذا تتلقى دالة الخادم كائنًا وتغير خصائصه، والخصائص على لا يتأثر العميل.

معالِجات النجاح

لأن الرمز من جهة العميل يستمر إلى السطر التالي بدون انتظار الخادم الاتصال لإكمال الطلب، withSuccessHandler(function) تحديد دالة استدعاء من جانب العميل لتشغيلها عندما يستخدم الخادم ويستجيب. إذا أرجعت دالة الخادم قيمة، فستمرر واجهة برمجة التطبيقات هذه القيمة إلى للدالة الجديدة كمعلمة.

يعرض المثال التالي تنبيه متصفح عند استجابة الخادم. ملاحظة أن عينة التعليمات البرمجية هذه تتطلب تفويضًا لأن الدالة من جانب الخادم تدخل إلى حسابك في Gmail. إنّ أبسط طريقة لمصادقة النص البرمجي هي تشغيله الدالة getUnreadEmails() يدويًا من أداة تعديل النصوص البرمجية مرة قبل لتحميل الصفحة. بدلاً من ذلك، عندما نشر تطبيق الويب، يمكنك اختيار لتنفيذه بصفتك "المستخدم الذي يصل إلى تطبيق الويب"، وفي هذه الحالة ستكون ستطلب الحصول على إذن عند تحميل التطبيق.

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function getUnreadEmails() {
  return GmailApp.getInboxUnreadCount();
}

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onSuccess(numUnread) {
        var div = document.getElementById('output');
        div.innerHTML = 'You have ' + numUnread
            + ' unread messages in your Gmail inbox.';
      }

      google.script.run.withSuccessHandler(onSuccess)
          .getUnreadEmails();
    </script>
  </head>
  <body>
    <div id="output"></div>
  </body>
</html>

معالِجات الأعطال

وفي حالة إخفاق الخادم في الاستجابة أو عرض خطأ، withFailureHandler(function) تحديد معالِج الإخفاق بدلاً من معالِج النجاح، وذلك باستخدام Error كائن (إن وُجد) تم تمريره كوسيطة.

بشكل افتراضي، إذا لم تحدد معالِجًا للإخفاق، يتم تسجيل الإخفاقات في وحدة تحكم JavaScript. لإلغاء هذه المشكلة، يمكنك الاتصال بالرقم withFailureHandler(null) أو طلب المعرّف. أي معالج إخفاق لا يفعل شيئًا.

وتكون بنية معالِجات الإخفاق مماثلة تقريبًا لمعالجات النجاح، حيث مثالنا.

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function getUnreadEmails() {
  // 'got' instead of 'get' will throw an error.
  return GmailApp.gotInboxUnreadCount();
}

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onFailure(error) {
        var div = document.getElementById('output');
        div.innerHTML = "ERROR: " + error.message;
      }

      google.script.run.withFailureHandler(onFailure)
          .getUnreadEmails();
    </script>
  </head>
  <body>
    <div id="output"></div>
  </body>
</html>

كائنات المستخدم

يمكنك إعادة استخدام معالج النجاح أو الإخفاق نفسه لعمليات استدعاء متعددة الخادم من خلال استدعاء withUserObject(object) لتحديد كائن سيتم تمريره إلى المعالج كمعلمة ثانية. هذا "كائن المستخدم" - يجب عدم الخلط بينه وبين صف User — يتيح لك الرد على السياق الذي اتصل فيه العميل بالخادم. لأنّ كائنات المستخدم يتم إرسالها إلى الخادم، فيمكن أن تكون أي شيء تقريبًا، بما في ذلك الدوال، ونموذج DOM والعناصر، وهكذا، دون القيود على المعلمات والقيم المعروضة لمكالمات الخادم. ومع ذلك، لا يمكن أن تكون كائنات المستخدم كائنات تم إنشاؤها باستخدام new.

في هذا المثال، سيؤدي النقر فوق أي من زرين إلى تحديث هذا الزر قيمة من الخادم مع ترك الزر الآخر بدون تغيير، على الرغم من مشاركة معالج واحد للنجاح. داخل معالج onclick، الكلمة الرئيسية this إلى button نفسها.

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function getEmail() {
  return Session.getActiveUser().getEmail();
}

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function updateButton(email, button) {
        button.value = 'Clicked by ' + email;
      }
    </script>
  </head>
  <body>
    <input type="button" value="Not Clicked"
      onclick="google.script.run
          .withSuccessHandler(updateButton)
          .withUserObject(this)
          .getEmail()" />
    <input type="button" value="Not Clicked"
      onclick="google.script.run
          .withSuccessHandler(updateButton)
          .withUserObject(this)
          .getEmail()" />
  </body>
</html>

النماذج

إذا استدعيت دالة خادم تستخدم عنصر form كمعلمة، فإن النموذج يصبح كائنًا واحدًا بأسماء حقول كمفاتيح وقيم حقول كقيم. تشير رسالة الأشكال البيانية يتم تحويل جميع القيم إلى سلاسل، باستثناء محتوى حقل إدخال الملف. التي تصبح كائنات Blob.

يعالج هذا المثال نموذجًا، بما في ذلك حقل إدخال الملف، بدون إعادة التحميل. الصفحة؛ تحمّل الملف على Google Drive ثم تطبع عنوان URL ملفك في الصفحة من جانب العميل. داخل معالج onsubmit، الكلمة الرئيسية this إلى النموذج نفسه. لاحظ أنه عند تحميل جميع النماذج في الصفحة سيتم إيقاف إجراء الإرسال التلقائي من خلال preventFormSubmit. وهذا يمنع الصفحة من إعادة التوجيه إلى عنوان URL غير دقيق في حالة وجود استثناء.

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function processForm(formObject) {
  var formBlob = formObject.myFile;
  var driveFile = DriveApp.createFile(formBlob);
  return driveFile.getUrl();
}

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      // Prevent forms from submitting.
      function preventFormSubmit() {
        var forms = document.querySelectorAll('form');
        for (var i = 0; i < forms.length; i++) {
          forms[i].addEventListener('submit', function(event) {
            event.preventDefault();
          });
        }
      }
      window.addEventListener('load', preventFormSubmit);

      function handleFormSubmit(formObject) {
        google.script.run.withSuccessHandler(updateUrl).processForm(formObject);
      }
      function updateUrl(url) {
        var div = document.getElementById('output');
        div.innerHTML = '<a href="' + url + '">Got it!</a>';
      }
    </script>
  </head>
  <body>
    <form id="myForm" onsubmit="handleFormSubmit(this)">
      <input name="myFile" type="file" />
      <input type="submit" value="Submit" />
    </form>
    <div id="output"></div>
 </body>
</html>

أدوات تنفيذ النصوص البرمجية

يمكنك اعتبار google.script.run أداة إنشاء "لأداة تشغيل النصوص البرمجية". إذا كنت إذا أضفت معالج نجاح أو معالِج أخطاء أو كائن مستخدم إلى مشغِّل النصوص البرمجية، لا تغيّر العدّاء الحالي بدلاً من ذلك، ستعود إلى مشغِّل نص برمجي جديد بالسلوك الجديد.

يمكنك استخدام أي مجموعة وأي ترتيب بقيمة withSuccessHandler(). withFailureHandler() وwithUserObject() يمكنك أيضًا استدعاء أي من تعديل الدوال في مشغِّل نصوص برمجية يحتوي بالفعل على مجموعة قيم. القيمة تتجاوز القيمة السابقة ببساطة.

يضبط هذا المثال معالج إخفاق شائعًا لجميع اتصالات الخادم الثلاثة، ولكن معالِجات نجاح منفصلة:

var myRunner = google.script.run.withFailureHandler(onFailure);
var myRunner1 = myRunner.withSuccessHandler(onSuccess);
var myRunner2 = myRunner.withSuccessHandler(onDifferentSuccess);

myRunner1.doSomething();
myRunner1.doSomethingElse();
myRunner2.doSomething();

الوظائف الخاصة

تُعتبر وظائف الخادم التي تنتهي أسماؤها بشرطة سفلية بمثابة دوال خاصة. لا يمكن استدعاء هذه الدوال بواسطة google.script ولا يتم تغيير أسمائها مطلقًا إرسال إلى العميل. وبالتالي، يمكنك استخدامها لإخفاء تفاصيل التنفيذ التي الحفاظ على سرية هذه المعلومات على الخادم. لا يمكن لـ "google.script" أيضًا الاطّلاع على التفاصيل. الدوال ضمن المكتبات والدوال التي ليست تم الإعلان عنه في المستوى الأعلى من النص البرمجي.

في هذا المثال، تتوفر الدالة getBankBalance() في البرنامج الرمز البرمجي يمكن للمستخدم الذي يفحص رمز المصدر اكتشاف اسمه حتى فلا تسميه. ومع ذلك، تكون الدالتان deepSecret_() وobj.objectMethod() غير مرئية تمامًا لـ للعميل.

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function getBankBalance() {
  var email = Session.getActiveUser().getEmail()
  return deepSecret_(email);
}

function deepSecret_(email) {
 // Do some secret calculations
 return email + ' has $1,000,000 in the bank.';
}

var obj = {
  objectMethod: function() {
    // More secret calculations
  }
};

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onSuccess(balance) {
        var div = document.getElementById('output');
        div.innerHTML = balance;
      }

      google.script.run.withSuccessHandler(onSuccess)
          .getBankBalance();
    </script>
  </head>
  <body>
    <div id="output">No result yet...</div>
  </body>
</html>

تغيير حجم مربعات الحوار في Google Workspace التطبيقات

مربعات حوار مخصصة في "مستندات Google" أو "جداول بيانات Google" يمكن تغيير حجم النماذج من خلال استدعاء طرق google.script.host setWidth(width) أو setHeight(height) بوصة التعليمات البرمجية من جانب العميل. (لضبط الحجم الأولي لمربّع حوار، استخدِم زر HtmlOutput طرق setWidth(width) أو setHeight(height).) لاحظ أنه لا يتم إعادة توسيط مربعات الحوار في النافذة الرئيسية عند تغيير حجمها، لا يمكن تغيير حجم الأشرطة الجانبية.

إغلاق مربّعات الحوار والأشرطة الجانبية في Google Workspace

إذا كنت تستخدم خدمة HTML لعرض مربع حوار أو الشريط الجانبي في "مستندات Google" أو "جداول بيانات Google" النماذج، لا يمكنك إغلاق الواجهة من خلال طلب الرقم window.close(). بدلاً من ذلك، يجب الاتصال google.script.host.close() على سبيل المثال، راجع القسم الذي يتناول عرض رمز HTML ك Google Workspace واجهة مستخدم.

جارٍ نقل تركيز المتصفّح في Google Workspace

لتبديل التركيز في متصفّح المستخدم من مربّع حوار أو الشريط الجانبي مرة أخرى إلى في "مستندات Google" أو "جداول بيانات Google" أو "أدوات تحرير النماذج"، ما عليك سوى استدعاء الطريقة google.script.host.editor.focus() وهذه الطريقة مفيدة بشكل خاص مع طرق خدمة المستندات Document.setCursor(position) أو Document.setSelection(range)