Lời hứa trong JavaScript là gì?
JavaScript là một luồng đơn, nghĩa là hai bit của tập lệnh không thể chạy cùng một lúc; họ phải chạy hết người này đến người khác. Promise là một đối tượng đại diện cho việc hoàn thành (hoặc thất bại) cuối cùng của một hoạt động không đồng bộ và giá trị kết quả của nó.
var promise = new Promise(function(resolve, reject) {
// do thing, then…
if (/* everything worked */) {
resolve("See, it worked!");
}
else {
reject(Error("It broke"));
}
});
Một Lời hứa tồn tại ở một trong những trạng thái này
- Đang chờ xử lý: trạng thái ban đầu, không hoàn thành cũng không bị từ chối.
- Đã hoàn thành: thao tác đã hoàn tất thành công.
- Bị từ chối: thao tác không thành công.
Đối tượng Promise hoạt động như proxy cho một giá trị không nhất thiết phải biết khi lời hứa được tạo. Nó cho phép bạn liên kết các trình xử lý với giá trị thành công cuối cùng hoặc lý do thất bại của hành động không đồng bộ.
Điều này cho phép các phương thức không đồng bộ trả về các giá trị giống như các phương thức đồng bộ: thay vì ngay lập tức trả về giá trị cuối cùng, phương thức không đồng bộ trả về một lời hứa cung cấp giá trị tại một thời điểm nào đó trong tương lai.
Sử dụng ‘Sau đó’ (Chuỗi lời hứa)
Để thực hiện một số cuộc gọi không đồng bộ và đồng bộ hóa chúng lần lượt, bạn có thể sử dụng chuỗi lời hứa. Điều này cho phép sử dụng một giá trị từ lời hứa đầu tiên trong các cuộc gọi lại tiếp theo.
Promise.resolve('some')
.then(function(string) { // <-- This will happen after the above Promise resolves (returning the value 'some')
return new Promise(function(resolve, reject) {
setTimeout(function() {
string += 'thing';
resolve(string);
}, 1);
});
})
.then(function(string) { // <-- This will happen after the above .then's new Promise resolves
console.log(string); // <-- Logs 'something' to the console
});
API lời hứa
Có 4 phương thức tĩnh trong lớp Promise:
- Promise.resolve
- Promise.reject
- Lời hứa.all
- lời hứa.race
Lời hứa có thể được xâu chuỗi lại với nhau
Khi viết Lời hứa để giải quyết một vấn đề cụ thể, bạn có thể xâu chuỗi chúng lại với nhau để tạo thành logic.
var add = function(x, y) {
return new Promise((resolve,reject) => {
var sum = x + y;
if (sum) {
resolve(sum);
}
else {
reject(Error("Could not add the two values!"));
}
});
};
var subtract = function(x, y) {
return new Promise((resolve, reject) => {
var sum = x - y;
if (sum) {
resolve(sum);
}
else {
reject(Error("Could not subtract the two values!"));
}
});
};
// Starting promise chain
add(2,2)
.then((added) => {
// added = 4
return subtract(added, 3);
})
.then((subtracted) => {
// subtracted = 1
return add(subtracted, 5);
})
.then((added) => {
// added = 6
return added * 2;
})
.then((result) => {
// result = 12
console.log("My result is ", result);
})
.catch((err) => {
// If any part of the chain is rejected, print the error message.
console.log(err);
});
Điều này hữu ích cho việc theo dõi một Lập trình chức năng mô hình. Bằng cách tạo các hàm để thao tác dữ liệu, bạn có thể xâu chuỗi chúng lại với nhau để tạo ra kết quả cuối cùng. Nếu tại bất kỳ điểm nào trong chuỗi chức năng, một giá trị là vật bị loại bỏ chuỗi sẽ bỏ qua gần nhất catch()
người xử lý.
Để biết thêm thông tin về Lập trình hàm: Lập trình hàm
Máy phát hàm
Trong các bản phát hành gần đây, JavaScript đã giới thiệu nhiều cách hơn để xử lý các Lời hứa một cách tự nhiên. Một cách như vậy là bộ tạo chức năng. Trình tạo hàm là các hàm “có thể tạm dừng”. Khi được sử dụng với Lời hứa, trình tạo có thể giúp việc sử dụng dễ đọc hơn rất nhiều và có vẻ “đồng bộ”.
const myFirstGenerator = function* () {
const one = yield 1;
const two = yield 2;
const three = yield 3;
return 'Finished!';
}
const gen = myFirstGenerator();
Đây là trình tạo đầu tiên của chúng tôi, mà bạn có thể nhìn thấy bằng function*
cú pháp. Các gen
biến chúng tôi khai báo sẽ không chạy myFirstGenerator
nhưng thay vào đó sẽ là “trình tạo này đã sẵn sàng để sử dụng”.
console.log(gen.next());
// Returns { value: 1, done: false }
Khi chúng ta chạy gen.next()
nó sẽ hủy tạm dừng trình tạo và tiếp tục. Vì đây là lần đầu tiên chúng tôi gọi gen.next()
nó sẽ chạy yield 1
và tạm dừng cho đến khi chúng tôi gọi gen.next()
lần nữa. Khi nào yield 1
được gọi, nó sẽ trả về cho chúng ta value
đã được mang lại và liệu trình tạo có hay không done
.
console.log(gen.next());
// Returns { value: 2, done: false }
console.log(gen.next());
// Returns { value: 3, done: false }
console.log(gen.next());
// Returns { value: 'Finished!', done: true }
console.log(gen.next());
// Will throw an error
Khi chúng tôi tiếp tục gọi gen.next()
nó sẽ tiếp tục đi vào tiếp theo yield
và tạm dừng mỗi lần. Một khi không còn nữa yield
‘ còn lại, nó sẽ tiếp tục chạy phần còn lại của trình tạo, trong trường hợp này chỉ đơn giản là trả về 'Finished!'
. Nếu bạn gọi gen.next()
một lần nữa, nó sẽ báo lỗi khi trình tạo kết thúc.
Bây giờ, hãy tưởng tượng nếu mỗi yield
trong ví dụ này là một Promise
bản thân mã sẽ xuất hiện cực kỳ đồng bộ.
Promise.all(iterable) rất hữu ích cho nhiều yêu cầu tới các nguồn khác nhau
Phương thức Promise.all(iterable) trả về một Lời hứa duy nhất được giải quyết khi tất cả các lời hứa trong đối số có thể lặp lại đã được giải quyết hoặc khi đối số có thể lặp lại không chứa lời hứa nào. Nó từ chối với lý do của lời hứa đầu tiên từ chối.
var promise1 = Promise.resolve(catSource);
var promise2 = Promise.resolve(dogSource);
var promise3 = Promise.resolve(cowSource);
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
});
// expected output: Array ["catData", "dogData", "cowData"]