Cú pháp yield lạ trong JavaScript
Tôi vừa xem qua task.js rất thú vị của Dave Herman. Trong ví dụ của anh ấy có dòng này:
var [foo, bar] = yield join(read("foo.json"),
read("bar.json")).timeout(1000);
Tôi quen thuộc với các generator nhưng tôi không hiểu cách biểu thức yield đánh giá thành một giá trị có thể gán cho [foo, bar]. Thực tế tôi sẽ không mong đợi biểu thức này có thể gán cho bất cứ thứ gì vì nó về cơ bản là cùng một thứ như return.
Cú pháp yield trong JS vẫn có vẻ hơi thiếu tài liệu và tôi không thể tìm thấy thông tin về điều này.
Vậy để làm rõ câu hỏi của tôi: cuối cùng thì foo và bar được gán giá trị gì?
Câu trả lời #1
Thực ra, đoạn văn liên quan nằm ngay phía dưới trong https://developer.mozilla.org/En/New_in_JavaScript_1.7:
Khi một generator đã được khởi động bằng cách gọi phương thức
next(), bạn có thể sử dụngsend(), truyền vào một giá trị cụ thể sẽ được coi là kết quả củayieldcuối cùng. Generator sau đó sẽ trả về toán hạng củayieldtiếp theo.
Tôi nghĩ điều này chỉ liên quan nếu bộ sinh được sử dụng bằng cách gọi trực tiếp các phương thức của nó, không phải khi lặp qua các giá trị của nó - một vòng lặp sẽ luôn gọi next() trên bộ sinh và không bao giờ gọi send().
Theo một cách nào đó, việc thực thi generator tương tự như đa nhiệm hợp tác. Generator sẽ thực thi cho đến khi gặp câu lệnh yield. Nó sẽ trả quyền điều khiển lại cho ai gọi next() hoặc send() trên generator. Người gọi sau đó tiếp tục thực thi, cho đến khi lần gọi next() hoặc send() tiếp theo được thực hiện - lúc này generator lại đang thực thi. Mỗi lần như vậy, các giá trị có thể được truyền qua lại.
Đây là một ví dụ đơn giản:
function gen()
{
var [foo, bar] = yield 1;
console.log("Generator got: " + foo + ", " + bar);
}
// This creates a generator but doesn't run it yet
var g = gen();
// Starts generator execution until a yield statement returns a value
var result = g.next()
console.log("Received from generator: " + result);
// Continue generator execution with [2, 3] being the return value
// of the yield statement. This will throw StopIteration because the
// iterator doesn't have any more yield statements.
g.send([2, 3]);
Câu trả lời #2
https://developer.mozilla.org/En/New_in_JavaScript_1.7
Hàm chứa từ khóa yield là một generator. Khi bạn gọi nó, các tham số chính thức của nó được ràng buộc với các đối số thực tế, nhưng phần thân của nó thực sự không được đánh giá. Thay vào đó, một generator-iterator được trả về. Mỗi lần gọi phương thức next() của generator-iterator thực hiện một lượt nữa qua thuật toán lặp. Giá trị của mỗi bước là giá trị được chỉ định bởi từ khóa yield. Hãy nghĩ về yield như phiên bản generator-iterator của return, chỉ ra ranh giới giữa mỗi vòng lặp của thuật toán. Mỗi khi bạn gọi next(), mã generator tiếp tục từ câu lệnh theo sau yield.
