Ngoại lệ trong chuỗi Promise JavaScript
Giả sử vì một lý do nào đó Promise của chúng ta bị từ chối (reject) với lỗi:
let promise = new Promise(function(resolve, reject) {
setTimeout(function() {
reject('error');
}, 3000);
});
Trong trường hợp này, việc thực thi mã sẽ ngay lập tức chuyển
đến phương thức then có trình xử lý lỗi (hàm thứ hai),
hoặc đến catch đầu tiên, tùy xem cái nào
được gặp trước.
Đây là ví dụ cho trường hợp thứ nhất:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
},
function(error) {
// Việc thực thi sẽ ngay lập tức chuyển đến đây
}
).then(
function(result) {
console.log(result);
}
);
Đây là ví dụ cho trường hợp thứ hai:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// Việc thực thi sẽ ngay lập tức chuyển đến đây
}
).then(
function(result) {
console.log(result);
}
);
Trình xử lý lỗi có hai lựa chọn hành động:
nếu nó xử lý được tình huống ngoại lệ,
nó có thể trả về kết quả thông qua return
và việc thực thi sẽ tiếp tục xuống chuỗi.
Nếu nó không xử lý được lỗi, nó có thể
hoặc không trả về gì, hoặc ném ra một ngoại lệ
bằng throw. Trong trường hợp này việc thực thi
sẽ chuyển đến trình bắt lỗi tiếp theo
(trong then hoặc catch - cái nào gặp
trước).
Thông thường, tất cả lỗi trong chuỗi được bắt
ở một chỗ: một catch được đặt ở cuối chuỗi:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// chúng ta sẽ vào đây trong trường hợp có lỗi
}
);
Trong đó, ngoại lệ có thể phát sinh từ chính
Promise, hoặc được ném ra bằng throw
tại bất kỳ mắt xích nào trong chuỗi:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
if (mọiThứTốtĐẹp) {
return result + '2';
} else {
throw new Error('lỗi'); // chuyển đến trình bắt lỗi gần nhất
}
}
)
.then(
function(result) {
return result + '3';
}
).catch(
function(error) {
// trình bắt lỗi gần nhất
}
);
Lưu ý rằng catch cần thiết chính để
chẩn đoán lỗi: nó có thể giải quyết được hay không.
Nếu lỗi có thể giải quyết, thì catch nên
chuyển giải pháp của nó đến then tiếp theo sau nó.
Còn nếu không thể giải quyết (hoặc bản thân catch này
đơn giản là không biết cách giải quyết nó), thì chúng ta nên
hoặc không trả về gì hoặc ném ra ngoại lệ:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
if (lỗiCóThểGiảiQuyết) {
return 'dữ liệu'; // gửi đến then tiếp theo
} else {
// không trả về gì hoặc ném ra ngoại lệ
}
}
).then(
function(result) {
// ở đây chúng ta giải quyết lỗi
}
);