Trong Apps Script và JavaScript, thời gian chạy hoặc môi trường thời gian chạy chứa công cụ JavaScript phân tích cú pháp và thực thi mã tập lệnh. Thời gian chạy cung cấp các quy tắc về cách truy cập vào bộ nhớ, cách chương trình có thể tương tác với hệ điều hành của máy tính và cú pháp chương trình nào là hợp lệ. Mỗi trình duyệt web đều có một môi trường thời gian chạy cho JavaScript.
Trước đây, Apps Script được hỗ trợ bởi trình thông dịch JavaScript Rhino của Mozilla. Mặc dù Rhino cung cấp một cách thuận tiện để Apps Script thực thi các tập lệnh của nhà phát triển, nhưng nó cũng liên kết Apps Script với một phiên bản JavaScript cụ thể (ES5). Nhà phát triển Apps Script không thể sử dụng cú pháp và các tính năng JavaScript hiện đại hơn trong tập lệnh bằng thời gian chạy Rhino.
Để giải quyết vấn đề này, Apps Script hiện được hỗ trợ bởi thời gian chạy V8 hỗ trợ Chrome và Node.js. Bạn có thể di chuyển các tập lệnh hiện có sang V8 để tận dụng cú pháp và các tính năng hiện đại của JavaScript.
Trang này mô tả các tính năng mới do V8 hỗ trợ và cách bạn có thể bật V8 để sử dụng trong tập lệnh của mình. Di chuyển tập lệnh sang V8 mô tả các bước di chuyển tập lệnh hiện có để sử dụng môi trường thời gian chạy V8.
Các tính năng của môi trường thời gian chạy V8
Các tập lệnh sử dụng môi trường thời gian chạy V8 có thể tận dụng các tính năng sau:
Cú pháp ECMAScript hiện đại
Bạn có thể sử dụng cú pháp ECMAScript hiện đại trong các tập lệnh được hỗ trợ bởi môi trường thời gian chạy V8. Cú pháp này bao gồm let, const và nhiều tính năng phổ biến khác.
Hãy xem Ví dụ về cú pháp V8 để biết danh sách ngắn các điểm cải tiến cú pháp phổ biến mà bạn có thể thực hiện bằng cách sử dụng môi trường thời gian chạy V8.
Cải thiện khả năng phát hiện chức năng
Tính năng phát hiện hàm Apps Script được cải thiện cho các tập lệnh sử dụng V8. Thời gian chạy mới nhận dạng các định dạng định nghĩa hàm sau:
function normalFunction() {} async function asyncFunction() {} function* generatorFunction() {} var varFunction = function() {} let letFunction = function() {} const constFunction = function() {} var namedVarFunction = function alternateNameVarFunction() {} let namedLetFunction = function alternateNameLetFunction() {} const namedConstFunction = function alternateNameConstFunction() {} var varAsyncFunction = async function() {} let letAsyncFunction = async function() {} const constAsyncFunction = async function() {} var namedVarAsyncFunction = async function alternateNameVarAsyncFunction() {} let namedLetAsyncFunction = async function alternateNameLetAsyncFunction() {} const namedConstAsyncFunction = async function alternateNameConstAsyncFunction() {} var varGeneratorFunction = function*() {} let letGeneratorFunction = function*() {} const constGeneratorFunction = function*() {} var namedVarGeneratorFunction = function* alternateNameVarGeneratorFunction() {} let namedLetGeneratorFunction = function* alternateNameLetGeneratorFunction() {} const namedConstGeneratorFunction = function* alternateNameConstGeneratorFunction() {} var varLambda = () => {} let letLambda = () => {} const constLambda = () => {} var varAsyncLambda = async () => {} let letAsyncLambda = async () => {} const constAsyncLambda = async () => {}
Gọi các phương thức đối tượng từ các trình kích hoạt và lệnh gọi lại
Các tập lệnh sử dụng V8 có thể gọi các phương thức đối tượng và phương thức tĩnh của lớp từ những nơi mà bạn đã có thể gọi các phương thức thư viện. Những nơi này bao gồm:
- Trình kích hoạt tệp kê khai của tiện ích bổ sung Google Workspace
- Điều kiện kích hoạt có thể cài đặt
- Các mục trong trình đơn của trình chỉnh sửa Google Workspace
- Hàm callback của người dùng, chẳng hạn như hàm được mô tả trong mẫu mã
ScriptApp.newStateToken().
Ví dụ sau đây về V8 cho thấy cách sử dụng các phương thức đối tượng khi tạo các mục trong trình đơn trong Google Trang tính:
function onOpen() {
const ui = SpreadsheetApp.getUi(); // Or DocumentApp, SlidesApp, or FormApp.
ui.createMenu('Custom Menu')
.addItem('First item', 'menu.item1')
.addSeparator()
.addSubMenu(ui.createMenu('Sub-menu')
.addItem('Second item', 'menu.item2'))
.addToUi();
}
const menu = {
item1: function() {
SpreadsheetApp.getUi().alert('You clicked: First item');
},
item2: function() {
SpreadsheetApp.getUi().alert('You clicked: Second item');
}
}
Xem nhật ký
Apps Script cung cấp hai dịch vụ ghi nhật ký: dịch vụ Logger và lớp console. Cả hai dịch vụ này đều ghi nhật ký vào cùng một dịch vụ Stackdriver Logging.
Để hiện nhật ký Logger và console, ở đầu trình chỉnh sửa tập lệnh, hãy nhấp vào Nhật ký thực thi.
Xem các lần thực thi
Để xem nhật ký thực thi của tập lệnh, hãy mở dự án Apps Script rồi nhấp vào Thực thi ở bên trái.
Ví dụ về cú pháp V8
Sau đây là danh sách ngắn các tính năng cú pháp phổ biến có sẵn cho các tập lệnh sử dụng thời gian chạy V8.
let và const
Các từ khoá let và const cho phép bạn lần lượt xác định các biến cục bộ trong phạm vi khối và các hằng số trong phạm vi khối.
// V8 runtime let s = "hello"; if (s === "hello") { s = "world"; console.log(s); // Prints "world" } console.log(s); // Prints "hello" const N = 100; N = 5; // Results in TypeError |
Hàm mũi tên
Hàm mũi tên cung cấp một cách ngắn gọn để xác định các hàm trong biểu thức.
// Rhino runtime function square(x) { return x * x; } console.log(square(5)); // Outputs 25 |
// V8 runtime const square = x => x * x; console.log(square(5)); // Outputs 25 // Outputs [1, 4, 9] console.log([1, 2, 3].map(x => x * x)); |
Lớp
Lớp cung cấp một phương tiện để sắp xếp mã theo khái niệm bằng tính kế thừa. Các lớp trong V8 chủ yếu là cú pháp đơn giản hơn so với cơ chế kế thừa dựa trên nguyên mẫu JavaScript.
// V8 runtime class Rectangle { constructor(width, height) { // class constructor this.width = width; this.height = height; } logToConsole() { // class method console.log(`Rectangle(width=${this.width}, height=${this.height})`); } } const r = new Rectangle(10, 20); r.logToConsole(); // Outputs Rectangle(width=10, height=20) |
Phép gán huỷ cấu trúc
Biểu thức phép gán phân rã là một cách nhanh chóng để giải nén các giá trị từ mảng và đối tượng thành các biến riêng biệt.
// Rhino runtime var data = {a: 12, b: false, c: 'blue'}; var a = data.a; var c = data.c; console.log(a, c); // Outputs 12 "blue" var a = [1, 2, 3]; var x = a[0]; var y = a[1]; var z = a[2]; console.log(x, y, z); // Outputs 1 2 3 |
// V8 runtime const data = {a: 12, b: false, c: 'blue'}; const {a, c} = data; console.log(a, c); // Outputs 12 "blue" const array = [1, 2, 3]; const [x, y, z] = array; console.log(x, y, z); // Outputs 1 2 3 |
Chuỗi mẫu
Chuỗi mẫu là chuỗi ký tự cho phép biểu thức được nhúng. Chúng giúp bạn tránh các câu lệnh nối chuỗi phức tạp hơn.
// Rhino runtime var name = 'Hi ' + first + ' ' + last + '.'; var url = 'http://localhost:3000/api/messages/' + id; |
// V8 runtime const name = `Hi ${first} ${last}.`; const url = `http://localhost:3000/api/messages/${id}`; |
Tham số mặc định
Tham số mặc định cho phép bạn chỉ định các giá trị mặc định cho các tham số của hàm trong khai báo hàm. Điều này có thể đơn giản hoá mã trong phần thân hàm vì bạn không cần phải chỉ định giá trị mặc định một cách rõ ràng cho các tham số bị thiếu.
// Rhino runtime function hello(greeting, name) { greeting = greeting || "hello"; name = name || "world"; console.log( greeting + " " + name + "!"); } hello(); // Outputs "hello world!" |
// V8 runtime const hello = function(greeting="hello", name="world") { console.log( greeting + " " + name + "!"); } hello(); // Outputs "hello world!" |
Chuỗi nhiều dòng
Bạn có thể xác định chuỗi nhiều dòng bằng cách sử dụng cùng một cú pháp như chữ ký mẫu. Giống như các chuỗi ký tự mẫu, cú pháp này giúp bạn tránh việc nối chuỗi và đơn giản hoá các định nghĩa chuỗi.
// Rhino runtime var multiline = "This string is sort of\n" + "like a multi-line string,\n" + "but it's not really one."; |
// V8 runtime const multiline = `This on the other hand, actually is a multi-line string, thanks to JavaScript ES6`; |
Các hạn chế về thời gian chạy V8
Môi trường thời gian chạy Apps Script V8 không phải là môi trường Node.js hoặc trình duyệt tiêu chuẩn. Điều này có thể dẫn đến các vấn đề về khả năng tương thích khi bạn gọi thư viện bên thứ ba hoặc điều chỉnh các ví dụ về mã từ các môi trường JavaScript khác.
API không dùng được
Các API JavaScript tiêu chuẩn sau đây KHÔNG có trong thời gian chạy V8 của Apps Script:
- Hẹn giờ:
setTimeout,setInterval,clearTimeout,clearInterval - Luồng phát:
ReadableStream,WritableStream,TextEncoder,TextDecoder - Web API:
fetch,FormData,File,Blob,URL,URLSearchParams,DOMException,atob,btoa - Crypto:
crypto,SubtleCrypto - Đối tượng chung:
window,navigator,performance,process(Node.js)
Sử dụng các API Apps Script sau đây làm giải pháp thay thế:
- Bộ hẹn giờ: Sử dụng
Utilities.sleepđể tạm dừng đồng bộ. Không hỗ trợ bộ hẹn giờ không đồng bộ. - Tìm nạp: Sử dụng
UrlFetchApp.fetch(url, params)để đưa ra các yêu cầu HTTP(S). - atob: Sử dụng
Utilities.base64Decodeđể giải mã các chuỗi được mã hoá Base64. - btoa: Sử dụng
Utilities.base64Encodeđể mã hoá các chuỗi trong Base64. - Tiền mã hoá: Sử dụng
Utilitiescho các hàm mật mã nhưcomputeDigest,computeHmacSha256SignaturevàcomputeRsaSha256Signature.
Đối với những API không có giải pháp thay thế bằng Apps Script, chẳng hạn như TextEncoder, đôi khi bạn có thể sử dụng một polyfill. Polyfill là một thư viện sao chép chức năng API không có sẵn theo mặc định trong môi trường thời gian chạy. Trước khi sử dụng polyfill, hãy xác nhận rằng polyfill đó tương thích với môi trường thời gian chạy V8 của Apps Script.
Các hạn chế không đồng bộ
Thời gian chạy V8 hỗ trợ cú pháp async và await cũng như đối tượng Promise.
Tuy nhiên, môi trường thời gian chạy Apps Script về cơ bản là đồng bộ.
- Microtask (Được hỗ trợ): Thời gian chạy xử lý hàng đợi microtask (nơi các lệnh gọi lại
Promise.thenvà độ phân giảiawaitxảy ra) sau khi ngăn xếp lệnh gọi hiện tại xoá. - Tác vụ lớn (Không được hỗ trợ): Apps Script không có vòng lặp sự kiện tiêu chuẩn cho các tác vụ lớn. Các hàm như
setTimeoutvàsetIntervalkhông dùng được. - Ngoại lệ WebAssembly: WebAssembly API là tính năng duy nhất được tích hợp sẵn hoạt động theo cách không chặn trong thời gian chạy, cho phép các mẫu biên dịch không đồng bộ cụ thể (WebAssembly.instantiate).
Tất cả các thao tác I/O, chẳng hạn như UrlFetchApp.fetch, đều chặn. Để đạt được các yêu cầu mạng song song, hãy sử dụng UrlFetchApp.fetchAll.
Giới hạn đối với lớp học
Thời gian chạy V8 có những hạn chế cụ thể liên quan đến các tính năng của lớp ES6+ hiện đại:
- Trường riêng tư: Các trường lớp riêng tư (ví dụ:
#field) không được hỗ trợ và gây ra lỗi phân tích cú pháp. Cân nhắc sử dụng các bao đóng hoặcWeakMapđể có tính năng đóng gói thực sự. - Trường tĩnh: Không hỗ trợ các khai báo trường tĩnh trực tiếp trong nội dung lớp (ví dụ:
static count = 0;). Chỉ định các thuộc tính tĩnh cho lớp sau khi xác định (ví dụ:MyClass.count = 0;).
Giới hạn của mô-đun
- Mô-đun ES6: Thời gian chạy V8 không hỗ trợ mô-đun ES6 (
import/export). Để sử dụng các thư viện, bạn phải sử dụng cơ chế thư viện Apps Script hoặc gói mã và các phần phụ thuộc của mã đó vào một tệp tập lệnh duy nhất. (Trình theo dõi vấn đề) - Thứ tự thực thi tệp: Tất cả các tệp kịch bản trong dự án của bạn đều được thực thi trong phạm vi toàn cục. Tốt nhất là bạn nên tránh mã cấp cao nhất có tác dụng phụ và đảm bảo các hàm và lớp được xác định trước khi được dùng trên các tệp. Sắp xếp rõ ràng các tệp trong trình chỉnh sửa nếu có các phần phụ thuộc giữa chúng.
Bật thời gian chạy V8
Nếu một tập lệnh đang sử dụng thời gian chạy Rhino, bạn có thể chuyển tập lệnh đó sang V8 bằng cách làm như sau:
- Mở dự án Apps Script.
- Ở bên trái, hãy nhấp vào Cài đặt dự án .
- Chọn hộp đánh dấu Bật hàm thời gian chạy bằng Chrome V8.
Ngoài ra, bạn có thể chỉ định trực tiếp thời gian chạy tập lệnh bằng cách chỉnh sửa tệp kê khai tập lệnh:
- Mở dự án Apps Script.
- Ở bên trái, hãy nhấp vào Cài đặt dự án .
- Chọn hộp đánh dấu Hiển thị tệp kê khai "appsscript.json" trong trình chỉnh sửa.
- Ở bên trái, hãy nhấp vào Trình chỉnh sửa >
appsscript.json. - Trong tệp kê khai
appsscript.json, hãy đặt trườngruntimeVersionthành giá trịV8. - Ở trên cùng, hãy nhấp vào Lưu dự án .
Bài viết Di chuyển tập lệnh sang V8 giải thích các bước khác mà bạn nên thực hiện để đảm bảo tập lệnh hoạt động tốt khi dùng V8.
Bật thời gian chạy Rhino
Nếu tập lệnh của bạn đang sử dụng V8 và bạn cần chuyển tập lệnh đó sang sử dụng môi trường thời gian chạy Rhino ban đầu, hãy làm như sau:
- Mở dự án Apps Script.
- Ở bên trái, hãy nhấp vào Cài đặt dự án .
- Xoá hộp đánh dấu Bật hàm thời gian chạy bằng Chrome V8.
Hoặc chỉnh sửa tệp kê khai tập lệnh:
- Mở dự án Apps Script.
- Ở bên trái, hãy nhấp vào Cài đặt dự án .
- Chọn hộp đánh dấu Hiển thị tệp kê khai "appsscript.json" trong trình chỉnh sửa.
- Ở bên trái, hãy nhấp vào Trình chỉnh sửa >
appsscript.json. - Trong tệp kê khai
appsscript.json, hãy đặt trườngruntimeVersionthành giá trịDEPRECATED_ES5. - Ở trên cùng, hãy nhấp vào Lưu dự án .
Làm cách nào để di chuyển các tập lệnh hiện có?
Hướng dẫn Di chuyển tập lệnh sang V8 mô tả các bước bạn cần thực hiện để di chuyển một tập lệnh hiện có sang sử dụng V8. Điều này bao gồm việc bật thời gian chạy V8 và kiểm tra tập lệnh để tìm mọi điểm không tương thích đã biết.
Tự động di chuyển tập lệnh sang V8
Kể từ ngày 18 tháng 2 năm 2020, Google sẽ bắt đầu từng bước di chuyển các tập lệnh hiện có vượt qua kiểm thử khả năng tương thích tự động của chúng tôi sang V8. Các tập lệnh bị ảnh hưởng vẫn hoạt động bình thường sau khi di chuyển.
Nếu bạn muốn chọn không di chuyển tự động một tập lệnh, hãy đặt trường runtimeVersion trong tệp kê khai của tập lệnh đó thành DEPRECATED_ES5. Sau đó, bạn có thể chọn di chuyển tập lệnh sang V8 theo cách thủ công bất cứ lúc nào.
Làm cách nào để báo cáo lỗi?
Hướng dẫn hỗ trợ giải thích cách nhận trợ giúp về lập trình trên Stack Overflow, tìm kiếm các báo cáo vấn đề hiện có, báo cáo lỗi mới và đưa ra yêu cầu về tính năng mới.