google.script.run
เป็น JavaScript API แบบไม่พร้อมกันฝั่งไคลเอ็นต์ ที่อนุญาตให้หน้าบริการ HTML เรียกใช้ฟังก์ชัน Apps Script ฝั่งเซิร์ฟเวอร์ได้ ตัวอย่างต่อไปนี้แสดงฟังก์ชันการทำงานพื้นฐานที่สุด ของ 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()
เบราว์เซอร์จะดำเนินการต่อในบรรทัดโค้ดถัดไปทันทีโดยไม่ต้องรอการตอบกลับ ซึ่งหมายความว่า การเรียกใช้ฟังก์ชันเซิร์ฟเวอร์อาจไม่ทำงานตามลำดับที่คุณคาดไว้ หากคุณเรียกใช้ฟังก์ชัน 2 รายการพร้อมกัน คุณจะไม่มีทางทราบว่าฟังก์ชันใดจะทำงานก่อน ผลลัพธ์อาจแตกต่างกันทุกครั้งที่คุณโหลดหน้าเว็บ ในกรณีนี้ ตัวแฮนเดิลที่สำเร็จและตัวแฮนเดิลที่ไม่สำเร็จ จะช่วยควบคุมโฟลว์ของโค้ด
google.script.run
API อนุญาตให้เรียกฟังก์ชันเซิร์ฟเวอร์พร้อมกันได้ 10 รายการ หากคุณโทรครั้งที่ 11 ในขณะที่ยังมีการโทร 10 สายอยู่ ฟังก์ชันเซิร์ฟเวอร์จะ ล่าช้าจนกว่าจะมีสายใดสายหนึ่งว่าง ในทางปฏิบัติ คุณไม่ควรต้องกังวลเกี่ยวกับข้อจำกัดนี้ โดยเฉพาะอย่างยิ่งเนื่องจากเบราว์เซอร์ส่วนใหญ่จำกัดจำนวนคำขอพร้อมกันไปยังเซิร์ฟเวอร์เดียวกันไว้ที่ต่ำกว่า 10 อยู่แล้ว เช่น ใน Firefox ขีดจำกัดคือ 6 เบราว์เซอร์ส่วนใหญ่จะหน่วงเวลาคำขอเซิร์ฟเวอร์ที่มากเกินไปในลักษณะเดียวกันจนกว่าคำขอที่มีอยู่รายการใดรายการหนึ่งจะเสร็จสมบูรณ์
พารามิเตอร์และค่าที่ส่งคืน
คุณเรียกใช้ฟังก์ชันเซิร์ฟเวอร์ด้วยพารามิเตอร์จากไคลเอ็นต์ได้ ในทำนองเดียวกัน ฟังก์ชันฝั่งเซิร์ฟเวอร์สามารถแสดงผลค่าไปยังไคลเอ็นต์เป็นพารามิเตอร์ที่ส่งไปยังตัวแฮนเดิลที่สำเร็จ
พารามิเตอร์และค่าที่ส่งคืนที่ถูกต้องคือค่าดั้งเดิมของ JavaScript เช่น Number
, Boolean
, String
หรือ null
รวมถึงออบเจ็กต์และอาร์เรย์ JavaScript ที่ ประกอบด้วยค่าดั้งเดิม ออบเจ็กต์ และอาร์เรย์ องค์ประกอบ form
ภายในหน้าเว็บ ยังถือเป็นพารามิเตอร์ที่ถูกต้องด้วย แต่ต้องเป็นพารามิเตอร์เดียวของฟังก์ชัน และ ไม่ถือเป็นค่าที่ส่งคืน คำขอจะล้มเหลวหากคุณพยายามส่งDate
, Function
, องค์ประกอบ DOM นอกเหนือจาก form
หรือประเภทอื่นๆ ที่ไม่อนุญาต รวมถึงประเภทที่ไม่อนุญาตภายในออบเจ็กต์หรืออาร์เรย์ ออบเจ็กต์ที่สร้างการอ้างอิงแบบวงกลมจะล้มเหลวเช่นกัน และฟิลด์ที่ไม่ได้กำหนดภายในอาร์เรย์จะกลายเป็น null
โปรดทราบว่าออบเจ็กต์ที่ส่งไปยังเซิร์ฟเวอร์จะกลายเป็นสำเนาของออบเจ็กต์เดิม หากฟังก์ชันเซิร์ฟเวอร์ได้รับออบเจ็กต์และเปลี่ยนพร็อพเพอร์ตี้ พร็อพเพอร์ตี้ในไคลเอ็นต์จะไม่ได้รับผลกระทบ
ตัวแฮนเดิลที่สำเร็จ
เนื่องจากโค้ดฝั่งไคลเอ็นต์จะไปยังบรรทัดถัดไปโดยไม่ต้องรอให้การเรียกเซิร์ฟเวอร์ เสร็จสมบูรณ์ withSuccessHandler(function)
จึงช่วยให้คุณระบุฟังก์ชันเรียกกลับฝั่งไคลเอ็นต์ที่จะเรียกใช้เมื่อเซิร์ฟเวอร์ ตอบกลับได้ หากฟังก์ชันเซิร์ฟเวอร์แสดงผลค่า API จะส่งค่าไปยัง ฟังก์ชันใหม่เป็นพารามิเตอร์
ตัวอย่างต่อไปนี้แสดงการแจ้งเตือนในเบราว์เซอร์เมื่อเซิร์ฟเวอร์ตอบกลับ โปรดทราบ ว่าตัวอย่างโค้ดนี้ต้องมีการให้สิทธิ์เนื่องจากฟังก์ชันฝั่งเซิร์ฟเวอร์ เข้าถึงบัญชี Gmail ของคุณ วิธีที่ง่ายที่สุดในการให้สิทธิ์สคริปต์คือการเรียกใช้ฟังก์ชัน getUnreadEmails()
ด้วยตนเองจากตัวแก้ไขสคริปต์ 1 ครั้งก่อนที่จะโหลดหน้าเว็บ หรือเมื่อติดตั้งใช้งานเว็บแอป คุณสามารถเลือก ให้ดำเนินการในฐานะ "ผู้ใช้ที่เข้าถึงเว็บแอป" ได้ ในกรณีนี้ ระบบจะ แจ้งให้คุณให้สิทธิ์เมื่อโหลดแอป
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)
เพื่อระบุออบเจ็กต์ที่จะส่งไปยังตัวแฮนเดิลเป็นพารามิเตอร์ที่ 2 "ออบเจ็กต์ผู้ใช้" นี้ (อย่าสับสนกับคลาส User
) ช่วยให้คุณตอบกลับบริบทที่ไคลเอ็นต์ติดต่อเซิร์ฟเวอร์ได้ เนื่องจากไม่ได้ส่งออบเจ็กต์ผู้ใช้ไปยังเซิร์ฟเวอร์ ออบเจ็กต์จึงเป็นอะไรก็ได้เกือบทุกอย่าง รวมถึงฟังก์ชัน องค์ประกอบ DOM และอื่นๆ โดยไม่มีข้อจำกัดเกี่ยวกับพารามิเตอร์และค่าที่ส่งคืนสำหรับการเรียกเซิร์ฟเวอร์ อย่างไรก็ตาม ออบเจ็กต์ผู้ใช้ต้องไม่ใช่ ออบเจ็กต์ที่สร้างด้วยตัวดำเนินการ new
ในตัวอย่างนี้ การคลิกปุ่มใดปุ่มหนึ่งจะอัปเดตปุ่มนั้นด้วย ค่าจากเซิร์ฟเวอร์โดยไม่เปลี่ยนแปลงปุ่มอื่น แม้ว่าปุ่มทั้ง 2 จะ ใช้ตัวแฮนเดิลการสำเร็จเดียวกันก็ตาม ภายใน 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
เป็นพารามิเตอร์ แบบฟอร์มจะกลายเป็นออบเจ็กต์เดียวที่มีชื่อฟิลด์เป็นคีย์และค่าฟิลด์เป็นค่า ค่าทั้งหมดจะได้รับการแปลงเป็นสตริง ยกเว้นเนื้อหาของฟิลด์ file-input ซึ่งจะกลายเป็นออบเจ็กต์ Blob
ตัวอย่างนี้จะประมวลผลแบบฟอร์ม รวมถึงช่องป้อนข้อมูลไฟล์ โดยไม่ต้องโหลดหน้าเว็บซ้ำ จากนั้นจะอัปโหลดไฟล์ไปยัง Google ไดรฟ์ แล้วพิมพ์ URL ของไฟล์ในหน้าฝั่งไคลเอ็นต์ ภายใน onsubmit
handler คีย์เวิร์ด 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()
นอกจากนี้ คุณยังเรียกใช้ฟังก์ชันการแก้ไขใดก็ได้ในเครื่องมือเรียกใช้สคริปต์ที่มีการตั้งค่าไว้แล้ว ค่าใหม่จะเขียนทับค่าก่อนหน้า
ตัวอย่างนี้ตั้งค่าเครื่องจัดการข้อผิดพลาดทั่วไปสำหรับการเรียกเซิร์ฟเวอร์ทั้ง 3 รายการ แต่มีเครื่องจัดการความสำเร็จ 2 รายการแยกกัน ดังนี้
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.script.host
setWidth(width)
หรือ setHeight(height)
ในโค้ดฝั่งไคลเอ็นต์ (หากต้องการตั้งค่าขนาดเริ่มต้นของกล่องโต้ตอบ ให้ใช้เมธอด HtmlOutput
setWidth(width)
และ setHeight(height)
) โปรดทราบว่ากล่องโต้ตอบจะไม่จัดกึ่งกลางในหน้าต่างหลักเมื่อมีการปรับขนาด และไม่สามารถปรับขนาดแถบด้านข้างได้
การปิดกล่องโต้ตอบและแถบด้านข้างใน Google Workspace
หากใช้บริการ HTML เพื่อแสดงกล่องโต้ตอบหรือแถบด้านข้างใน Google เอกสาร, ชีต หรือฟอร์ม คุณจะปิดอินเทอร์เฟซโดยการเรียก window.close()
ไม่ได้ แต่คุณต้องเรียกใช้ google.script.host.close()
แทน ดูตัวอย่างได้ที่ส่วนเกี่ยวกับการแสดง HTML เป็น Google Workspace อินเทอร์เฟซผู้ใช้
การย้ายโฟกัสของเบราว์เซอร์ใน Google Workspace
หากต้องการเปลี่ยนโฟกัสในเบราว์เซอร์ของผู้ใช้จากกล่องโต้ตอบหรือแถบด้านข้างกลับไปที่เครื่องมือแก้ไข Google เอกสาร, ชีต หรือฟอร์ม ให้เรียกใช้เมธอด google.script.host.editor.focus()
วิธีนี้มีประโยชน์อย่างยิ่งเมื่อใช้ร่วมกับเมธอด Document service Document.setCursor(position)
และ Document.setSelection(range)