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 طلبات متزامنة لوظائف الخادم. إذا
أجريت مكالمة 11 بينما لا تزال 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" من خلال استدعاء google.script.host
setWidth(width)
أو
setHeight(height)
في
الرمز البرمجي على جانب العميل. (لضبط الحجم الأولي لمربّع حوار، استخدِم طريقتَي HtmlOutput
setWidth(width)
و
setHeight(height)
.)
يُرجى العلم أنّه لا تتم إعادة توسيط مربّعات الحوار في النافذة الرئيسية عند تغيير حجمها، ولا يمكن
تغيير حجم الأشرطة الجانبية.
إغلاق مربّعات الحوار والألواح الجانبية في Google Workspace
إذا كنت تستخدم خدمة HTML لعرض مربع حوار أو شريط جانبي في "مستندات Google" أو "جداول بيانات Google" أو "نماذج Google"، لا يمكنك إغلاق الواجهة من خلال طلب window.close()
. بدلاً من ذلك، عليك
استدعاء
google.script.host.close()
.
على سبيل المثال، اطّلِع على القسم المعنيّ بموضوع
عرض صفحات HTML ك Google Workspace واجهة مستخدم.
نقل تركيز المتصفّح في Google Workspace
لتبديل التركيز في متصفّح المستخدم من مربّع حوار أو شريط جانبي إلى
أداة تحرير "مستندات Google" أو "جداول بيانات Google" أو "نماذج Google"، ما عليك سوى استدعاء الأسلوب
google.script.host.editor.focus()
.
تكون هذه الطريقة مفيدة بشكل خاص عند استخدامها مع أسلوبَي
خدمة المستندات
Document.setCursor(position)
و
Document.setSelection(range)
.