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 จุด ในทางปฏิบัติ คุณไม่ควรต้องคํานึงถึงข้อจํากัดนี้ โดยเฉพาะเนื่องจากเบราว์เซอร์ส่วนใหญ่จํากัดคําขอหลายรายการพร้อมกันไปยังเซิร์ฟเวอร์เดียวกันที่ตัวเลขต่ํากว่า 10 อยู่แล้ว
เช่น Firefox จะมีขีดจํากัดอยู่ที่ 6 รายการ เบราว์เซอร์ส่วนใหญ่จะชะลอคําขอของเซิร์ฟเวอร์ที่มากเกินไปไปจนกระทั่งคําขอที่มีอยู่คําขอหนึ่งเสร็จสิ้น
พารามิเตอร์และค่าที่ส่งคืน
คุณเรียกใช้ฟังก์ชันของเซิร์ฟเวอร์ด้วยพารามิเตอร์จากไคลเอ็นต์ได้ ในทํานองเดียวกัน ฟังก์ชันเซิร์ฟเวอร์อาจส่งคืนค่ากลับไปยังไคลเอ็นต์เป็นพารามิเตอร์ที่ส่งไปยังเครื่องจัดการความสําเร็จ
พารามิเตอร์ทางกฎหมายและผลที่ได้คือ JavaScript เบื้องต้น เช่น Number
,
Boolean
, String
หรือ null
รวมถึงออบเจ็กต์และอาร์เรย์ JavaScript ที่ประกอบด้วยค่าดั้งเดิม ออบเจ็กต์ และอาร์เรย์ องค์ประกอบ form
ภายในหน้ายังคงถูกกฎหมายในฐานะพารามิเตอร์ด้วย แต่ต้องเป็นพารามิเตอร์เดียวของฟังก์ชันและพารามิเตอร์ดังกล่าวไม่ถือว่าเป็นค่าที่ส่งคืน คําขอจะล้มเหลวหากคุณพยายามส่ง Date
, Function
, เอลิเมนต์ DOM ที่ไม่ใช่ form
หรือประเภทอื่นๆ ที่ไม่ได้รับอนุญาต ซึ่งรวมถึงประเภทต้องห้ามในออบเจ็กต์หรืออาร์เรย์ นอกจากนี้ออบเจ็กต์ที่สร้างการอ้างอิงแบบวงกลมจะล้มเหลวด้วยเช่นกัน และช่องที่ไม่ระบุภายในอาร์เรย์จะกลายเป็น null
โปรดทราบว่าออบเจ็กต์ที่ส่งผ่านไปยังเซิร์ฟเวอร์จะกลายเป็นสําเนาของต้นฉบับ หากฟังก์ชันเซิร์ฟเวอร์ได้รับออบเจ็กต์และเปลี่ยนแปลงพร็อพเพอร์ตี้ พร็อพเพอร์ตี้ในไคลเอ็นต์จะไม่ได้รับผลกระทบ
เครื่องจัดการความสําเร็จ
เนื่องจากโค้ดฝั่งไคลเอ็นต์ยังคงปรากฏอยู่ในบรรทัดถัดไปโดยไม่ต้องรอให้การเรียกเซิร์ฟเวอร์เสร็จสมบูรณ์
withSuccessHandler(function)
ช่วยให้คุณระบุฟังก์ชันเรียกกลับฝั่งไคลเอ็นต์เพื่อทํางานเมื่อเซิร์ฟเวอร์ตอบกลับ
หากฟังก์ชันเซิร์ฟเวอร์แสดงผลค่า API จะส่งค่าไปยังฟังก์ชันใหม่เป็นพารามิเตอร์
ตัวอย่างต่อไปนี้แสดงการแจ้งเตือนของเบราว์เซอร์เมื่อเซิร์ฟเวอร์ตอบสนอง โปรดทราบว่าตัวอย่างโค้ดนี้ต้องได้รับสิทธิ์เนื่องจากฟังก์ชันฝั่งเซิร์ฟเวอร์เข้าถึงบัญชี 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)
เพื่อระบุออบเจ็กต์ที่จะส่งไปยังเครื่องจัดการเป็นพารามิเตอร์ที่ 2
"ออบเจ็กต์ผู้ใช้" นี้ โปรดอย่าสับสนกับคลาส User
ทําให้คุณตอบกลับบริบทที่ไคลเอ็นต์ติดต่อเซิร์ฟเวอร์ได้ เนื่องจากไม่มีการส่งออบเจ็กต์ผู้ใช้ไปยังเซิร์ฟเวอร์ ออบเจ็กต์จึงทํางานได้เกือบทุกอย่าง รวมถึงฟังก์ชัน องค์ประกอบ DOM และอื่นๆ โดยไม่มีข้อจํากัดเกี่ยวกับพารามิเตอร์และค่าที่ส่งคืนสําหรับการเรียกเซิร์ฟเวอร์ แต่ออบเจ็กต์ผู้ใช้จะเป็นออบเจ็กต์ที่สร้างขึ้นด้วยโอเปอเรเตอร์ new
ไม่ได้
ในตัวอย่างนี้ การคลิกปุ่มใดปุ่มหนึ่งจาก 2 ปุ่มจะอัปเดตปุ่มนั้นด้วยค่าจากเซิร์ฟเวอร์โดยไม่เปลี่ยนปุ่มอีกปุ่ม แม้ว่าจะใช้ปุ่มเครื่องจัดการสําเร็จ 1 ตัวก็ตาม ในเครื่องจัดการ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 ไดรฟ์ แล้วพิมพ์ 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()
คุณยังเรียกใช้ฟังก์ชันการแก้ไขใดๆ ในตัวเรียกใช้สคริปต์ที่ตั้งค่าค่าไว้แล้วได้ด้วย ค่าใหม่จะลบล้างค่าก่อนหน้า
ตัวอย่างนี้จะกําหนดเครื่องจัดการความล้มเหลวทั่วไปสําหรับการเรียกเซิร์ฟเวอร์ทั้ง 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.setCursor(position)
และ Document.setSelection(range)