Lời hứa có thể được "xử lý" sau khi chúng bị từ chối. Đó là, người ta có thể gọi lại cuộc gọi từ chối lời hứa trước khi cung cấp trình xử lý bắt. Hành vi này hơi khó chịu với tôi vì người ta có thể viết ...
var promise = new Promise(function(resolve) {
kjjdjf(); // this function does not exist });
... Và trong trường hợp này, Promise bị từ chối âm thầm. Nếu một người quên thêm trình xử lý bắt, mã sẽ tiếp tục chạy âm thầm mà không có lỗi. Điều này có thể dẫn đến các lỗi kéo dài và khó tìm.
Trong trường hợp của Node.js, có thảo luận về việc xử lý các từ chối Promise chưa được xử lý này và báo cáo các vấn đề. Điều này đưa tôi đến ES7 async / await. Xem xét ví dụ này:
async function getReadyForBed() {
let teethPromise = brushTeeth();
let tempPromise = getRoomTemperature();
// Change clothes based on room temperature
let temp = await tempPromise;
// Assume `changeClothes` also returns a Promise
if(temp > 20) {
await changeClothes("warm");
} else {
await changeClothes("cold");
}
await teethPromise;
}
Trong ví dụ trên, giả sử răngPromise đã bị từ chối (Lỗi: hết kem đánh răng!) Trước khi getRoomTem Nhiệt độ được hoàn thành. Trong trường hợp này, sẽ có một từ chối Promise chưa được xử lý cho đến khi chờ đợi răngPromise.
Quan điểm của tôi là ... nếu chúng ta coi các từ chối Promise chưa được xử lý là một vấn đề, thì các Promise sau đó được xử lý bởi một sự chờ đợi có thể vô tình được báo cáo là lỗi. Sau đó, một lần nữa, nếu chúng tôi coi các từ chối Promise chưa được xử lý là không có vấn đề, các lỗi hợp pháp có thể không được báo cáo.
Suy nghĩ về điều này?
Điều này có liên quan đến cuộc thảo luận được tìm thấy trong dự án Node.js tại đây:
Hành vi phát hiện từ chối không được xử lý mặc định
nếu bạn viết mã theo cách này:
function getReadyForBed() {
let teethPromise = brushTeeth();
let tempPromise = getRoomTemperature();
// Change clothes based on room temperature
return Promise.resolve(tempPromise)
.then(temp => {
// Assume `changeClothes` also returns a Promise
if (temp > 20) {
return Promise.resolve(changeClothes("warm"));
} else {
return Promise.resolve(changeClothes("cold"));
}
})
.then(teethPromise)
.then(Promise.resolve()); // since the async function returns nothing, ensure it's a resolved promise for `undefined`, unless it's previously rejected
}
Khi getReadyForBed được gọi, nó sẽ tạo đồng bộ lời hứa (không trả lại) cuối cùng - sẽ có lỗi "từ chối không xử lý" giống như bất kỳ lời hứa nào khác (tất nhiên là không có gì, tùy thuộc vào động cơ). (Tôi thấy rất kỳ lạ khi hàm của bạn không trả về bất cứ thứ gì, điều đó có nghĩa là hàm async của bạn tạo ra một lời hứa không xác định.
Nếu tôi thực hiện Lời hứa ngay bây giờ mà không bắt và thêm một lần sau, hầu hết các triển khai "lỗi từ chối chưa xử lý" sẽ thực sự rút lại cảnh báo khi tôi xử lý sau. Nói cách khác, async / await không làm thay đổi cuộc thảo luận "từ chối không được xử lý" theo bất kỳ cách nào tôi có thể thấy.
để tránh cạm bẫy này, xin vui lòng viết mã theo cách này:
async function getReadyForBed() {
let teethPromise = brushTeeth();
let tempPromise = getRoomTemperature();
// Change clothes based on room temperature
var clothesPromise = tempPromise.then(function(temp) {
// Assume `changeClothes` also returns a Promise
if(temp > 20) {
return changeClothes("warm");
} else {
return changeClothes("cold");
}
});
/* Note that clothesPromise resolves to the result of `changeClothes`
due to Promise "chaining" magic. */
// Combine promises and await them both
await Promise.all(teethPromise, clothesPromise);
}
Lưu ý rằng điều này sẽ ngăn chặn bất kỳ lời từ chối lời hứa nào.