google.script.run
là một trình xử lý không đồng bộ
API JavaScript phía máy khách cho phép các trang dịch vụ HTML gọi phía máy chủ
Các hàm của Apps Script. Ví dụ sau đây cho thấy chức năng cơ bản nhất của google.script.run
– gọi một hàm trên máy chủ từ JavaScript phía máy khách.
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>
Nếu bạn triển khai tập lệnh này dưới dạng ứng dụng web và truy cập vào URL của ứng dụng, bạn sẽ không thấy
bất kỳ thứ gì, nhưng nếu xem nhật ký, bạn sẽ thấy chức năng máy chủ
Đã gọi doSomething()
.
Các lệnh gọi phía máy khách đến các hàm phía máy chủ không đồng bộ: sau trình duyệt
yêu cầu máy chủ chạy hàm doSomething()
, thì trình duyệt sẽ tiếp tục
ngay lập tức sang dòng mã tiếp theo mà không cần chờ phản hồi. Điều này có nghĩa là các lệnh gọi hàm máy chủ có thể không thực thi theo thứ tự bạn mong đợi. Nếu bạn thực hiện
hai lệnh gọi hàm cùng một lúc, nên không có cách nào để biết hàm nào sẽ
chạy trước; kết quả có thể khác nhau mỗi khi bạn tải trang. Trong trường hợp này,
trình xử lý thành công và trình xử lý lỗi
giúp kiểm soát luồng mã của bạn.
API google.script.run
cho phép 10 lệnh gọi đồng thời đến các hàm máy chủ. Nếu
bạn thực hiện lệnh gọi thứ 11 trong khi 10 vẫn đang chạy, hàm máy chủ sẽ là
hoãn cho đến khi một trong 10 suất tham gia được giải phóng. Trên thực tế, bạn hiếm khi phải
cần xem xét hạn chế này, đặc biệt là vì hầu hết các trình duyệt đã hạn chế
số lượng yêu cầu đồng thời đến cùng một máy chủ ở con số nhỏ hơn 10.
Ví dụ: Trong Firefox, giới hạn là 6. Hầu hết trình duyệt đều trì hoãn thời gian vượt quá mức tương tự
máy chủ cho đến khi một trong các yêu cầu hiện tại được hoàn tất.
Tham số và giá trị trả về
Bạn có thể gọi một hàm máy chủ bằng các tham số từ ứng dụng. Tương tự, một máy chủ có thể trả về một giá trị cho máy khách dưới dạng một tham số được truyền đến trình xử lý thành công.
Các tham số hợp lệ và giá trị trả về là các giá trị gốc JavaScript như Number
, Boolean
, String
hoặc null
, cũng như các đối tượng và mảng JavaScript được tạo thành từ các giá trị gốc, đối tượng và mảng. Phần tử form
trong trang
cũng hợp pháp dưới dạng tham số, nhưng phải là tham số duy nhất của hàm và
thì giá trị trả về không được phép. Yêu cầu không thành công nếu bạn cố gắng chuyển một
Date
, Function
, phần tử DOM ngoài form
hoặc loại bị cấm khác,
bao gồm cả các loại bị cấm bên trong đối tượng hoặc mảng. Đối tượng tạo
tham chiếu vòng tròn cũng sẽ không thành công và các trường không xác định trong mảng sẽ trở thành
null
.
Lưu ý rằng một đối tượng được truyền đến máy chủ sẽ trở thành bản sao của đối tượng gốc. Nếu một hàm máy chủ nhận một đối tượng và thay đổi thuộc tính của đối tượng đó, các thuộc tính trên khách hàng không bị ảnh hưởng.
Trình xử lý thành công
Vì mã phía máy khách tiếp tục sang dòng tiếp theo mà không cần đợi máy chủ
lệnh gọi để hoàn thành,
withSuccessHandler(function)
cho phép bạn chỉ định hàm callback phía máy khách để chạy khi máy chủ
phản hồi. Nếu hàm máy chủ trả về một giá trị, API sẽ chuyển giá trị đó đến
hàm mới dưới dạng tham số.
Ví dụ sau đây cho thấy một cảnh báo của trình duyệt khi máy chủ phản hồi. Ghi chú
mã mẫu này yêu cầu uỷ quyền vì hàm phía máy chủ
truy cập vào tài khoản Gmail của bạn. Cách đơn giản nhất để uỷ quyền tập lệnh là chạy
hàm getUnreadEmails()
theo cách thủ công từ trình chỉnh sửa tập lệnh một lần trước khi bạn
tải trang. Ngoài ra, khi triển khai ứng dụng web, bạn có thể chọn thực thi ứng dụng đó dưới dạng "người dùng truy cập vào ứng dụng web". Trong trường hợp này, bạn sẽ được nhắc cấp quyền khi tải ứng dụng.
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>
Trình xử lý lỗi
Trong trường hợp máy chủ không phản hồi hoặc gửi lỗi,
withFailureHandler(function)
cho phép bạn chỉ định một trình xử lý lỗi thay vì một trình xử lý thành công,
Error
được truyền dưới dạng đối số.
Theo mặc định, nếu bạn không chỉ định trình xử lý lỗi, lỗi sẽ được ghi vào
Bảng điều khiển JavaScript. Để ghi đè giá trị này, hãy gọi withFailureHandler(null)
hoặc cung cấp
một trình xử lý lỗi không làm gì cả.
Cú pháp cho trình xử lý lỗi gần giống với trình xử lý thành công, vì cú pháp này chương trình ví dụ.
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>
Đối tượng người dùng
Bạn có thể sử dụng lại cùng một trình xử lý thành công hoặc không thành công cho nhiều lệnh gọi đến máy chủ bằng cách gọi withUserObject(object)
để chỉ định một đối tượng sẽ được truyền đến trình xử lý dưới dạng tham số thứ hai.
"Đối tượng người dùng" này. Bạn không được nhầm lẫn với
Lớp User
– cho phép bạn trả lời
ngữ cảnh trong đó máy khách đã liên hệ với máy chủ. Bởi vì đối tượng người dùng không phải
được gửi đến máy chủ, chúng có thể là hầu hết mọi thứ, bao gồm các hàm, DOM
các phần tử, v.v. mà không bị hạn chế về tham số và giá trị trả về
cho lệnh gọi máy chủ. Tuy nhiên, đối tượng người dùng không thể là đối tượng được tạo bằng
Toán tử new
.
Trong ví dụ này, thao tác nhấp vào một trong hai nút sẽ cập nhật nút đó thành
từ máy chủ trong khi vẫn giữ nguyên nút còn lại, ngay cả khi chúng
chia sẻ một trình xử lý thành công. Bên trong trình xử lý onclick
, từ khoá this
tham chiếu đến chính 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>
Biểu mẫu
Nếu bạn gọi một hàm máy chủ có tham số là phần tử form
, thì biểu mẫu
trở thành một đối tượng duy nhất có tên trường là khoá và giá trị trường là giá trị. Chiến lược phát hành đĩa đơn
tất cả giá trị đều được chuyển đổi thành chuỗi, ngoại trừ nội dung của đầu vào tệp
các trường để trở thành đối tượng Blob
.
Ví dụ này xử lý một biểu mẫu, bao gồm cả trường nhập tệp, mà không cần tải lại trang; biểu mẫu này sẽ tải tệp lên Google Drive, sau đó in URL của tệp trong trang phía máy khách. Bên trong trình xử lý onsubmit
, từ khoá this
đề cập đến chính biểu mẫu đó. Xin lưu ý rằng khi tải tất cả biểu mẫu trong trang,
hành động gửi mặc định bị vô hiệu hoá bởi preventFormSubmit
. Điều này ngăn chặn
trang khỏi chuyển hướng đến một URL không chính xác trong trường hợp ngoại lệ.
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>
Trình chạy tập lệnh
Bạn có thể xem google.script.run
là trình tạo cho một "trình chạy tập lệnh". Nếu bạn
thêm trình xử lý thành công, trình xử lý lỗi hoặc đối tượng người dùng vào trình chạy tập lệnh, bạn
không thay đổi trình chạy hiện tại; thay vào đó, bạn sẽ lấy lại một trình chạy tập lệnh mới
bằng hành vi mới.
Bạn có thể sử dụng mọi tổ hợp và thứ tự bất kỳ của withSuccessHandler()
,
withFailureHandler()
và withUserObject()
. Bạn cũng có thể gọi bất kỳ
sửa đổi các hàm trên trình chạy tập lệnh đã có bộ giá trị. Gói thuê bao mới
chỉ ghi đè giá trị trước đó.
Ví dụ này thiết lập một trình xử lý lỗi chung cho cả 3 lệnh gọi máy chủ, nhưng có 2 trình xử lý thành công riêng biệt:
var myRunner = google.script.run.withFailureHandler(onFailure);
var myRunner1 = myRunner.withSuccessHandler(onSuccess);
var myRunner2 = myRunner.withSuccessHandler(onDifferentSuccess);
myRunner1.doSomething();
myRunner1.doSomethingElse();
myRunner2.doSomething();
Hàm riêng tư
Các hàm máy chủ có tên kết thúc bằng dấu gạch dưới được coi là riêng tư.
Không thể gọi các hàm này bằng google.script
và tên của các hàm này tuyệt đối không
được gửi đến máy khách. Do đó, bạn có thể dùng chúng để ẩn các chi tiết triển khai
cần được giữ bí mật trên máy chủ. google.script
cũng không xem được
các hàm trong thư viện và những hàm không phải là
được khai báo ở cấp cao nhất của tập lệnh.
Trong ví dụ này, hàm getBankBalance()
có trong ứng dụng
mã; người dùng kiểm tra mã nguồn của bạn có thể khám phá tên của mã nguồn đó ngay cả khi bạn
đừng gọi nó. Tuy nhiên, các hàm deepSecret_()
và obj.objectMethod()
hoàn toàn không hiển thị với
khách hàng.
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>
Đổi kích thước hộp thoại trong Google Workspace ứng dụng
Hộp thoại tuỳ chỉnh trong Google Tài liệu, Trang tính hoặc
Có thể đổi kích thước biểu mẫu bằng cách gọi phương thức
google.script.host
phương thức
setWidth(width)
hoặc
setHeight(height)
inch
mã phía máy khách. (Để đặt kích thước ban đầu của hộp thoại, hãy sử dụng các phương thức HtmlOutput
setWidth(width)
và setHeight(height)
.) Lưu ý rằng các hộp thoại không căn giữa lại trong cửa sổ mẹ khi đổi kích thước và bạn không thể đổi kích thước bảng điều khiển bên.
Đóng hộp thoại và thanh bên trong Google Workspace
Nếu bạn sử dụng dịch vụ HTML để hiển thị
hộp thoại hoặc thanh bên trong Google Tài liệu, Trang tính hoặc
Biểu mẫu, bạn không thể đóng giao diện bằng cách gọi window.close()
. Thay vào đó, bạn phải gọi google.script.host.close()
.
Để biết ví dụ, hãy xem phần về
phân phát HTML dưới dạng một Google Workspace giao diện người dùng.
Đang di chuyển tiêu điểm của trình duyệt trong Google Workspace
Để chuyển tiêu điểm trong trình duyệt của người dùng từ hộp thoại hoặc thanh bên trở lại trình chỉnh sửa Google Tài liệu, Trang tính hoặc Biểu mẫu, bạn chỉ cần gọi phương thức google.script.host.editor.focus()
.
Phương thức này đặc biệt hữu ích khi kết hợp với các phương thức Dịch vụ tài liệu Document.setCursor(position)
và Document.setSelection(range)
.