Vì vậy, về cơ bản bạn đang hỏi sự khác biệt giữa hai điều này là gì (đâu p
là lời hứa được tạo từ một số mã trước đó):
return p.then(...).catch(...);
và
return p.catch(...).then(...);
Có những khác biệt khi p giải quyết hoặc từ chối, nhưng liệu những khác biệt đó có quan trọng hay không phụ thuộc vào những gì mã bên trong .then()
hoặc .catch()
trình xử lý thực hiện.
Điều gì xảy ra khi p
giải quyết:
Trong lược đồ đầu tiên, khi p
giải quyết xong, .then()
trình xử lý được gọi. Nếu .then()
trình xử lý đó trả về một giá trị hoặc một lời hứa khác cuối cùng cũng được giải quyết, thì .catch()
trình xử lý sẽ bị bỏ qua. Tuy nhiên, nếu .then()
trình xử lý ném hoặc trả về một lời hứa cuối cùng bị từ chối, thì .catch()
trình xử lý sẽ thực hiện cho cả một lời từ chối trong lời hứa ban đầu p
, nhưng cũng có một lỗi xảy ra trong .then()
trình xử lý.
Trong lược đồ thứ hai, khi p
giải quyết xong, .then()
trình xử lý được gọi. Nếu .then()
trình xử lý đó ném hoặc trả về một lời hứa mà cuối cùng bị từ chối, thì .catch()
trình xử lý không thể nắm bắt điều đó vì nó nằm trước nó trong chuỗi.
Vì vậy, đó là sự khác biệt số 1. Nếu .catch()
trình xử lý SAU, thì nó cũng có thể bắt lỗi bên trong .then()
trình xử lý.
Điều gì xảy ra khi p
từ chối:
Bây giờ, trong lược đồ đầu tiên, nếu lời hứa p
từ chối, thì .then()
trình xử lý bị bỏ qua và .catch()
trình xử lý sẽ được gọi như bạn mong đợi. Những gì bạn làm trong .catch()
trình xử lý xác định những gì được trả về là kết quả cuối cùng. Nếu bạn chỉ trả về một giá trị từ .catch()
trình xử lý hoặc trả về một lời hứa cuối cùng được giải quyết, thì chuỗi hứa hẹn sẽ chuyển sang trạng thái đã giải quyết vì bạn đã "xử lý" lỗi và trở lại bình thường. Nếu bạn ném hoặc trả lại một lời hứa bị từ chối trong .catch()
trình xử lý, thì lời hứa được trả lại vẫn bị từ chối.
Trong sơ đồ thứ hai, nếu lời hứa p
từ chối, thì .catch()
trình xử lý được gọi. Nếu bạn trả về một giá trị bình thường hoặc một lời hứa cuối cùng được giải quyết từ .catch()
trình xử lý (do đó "xử lý" lỗi), thì chuỗi hứa sẽ chuyển sang trạng thái đã giải quyết và .then()
trình xử lý sau khi .catch()
sẽ được gọi.
Vì vậy, đó là sự khác biệt # 2. Nếu .catch()
trình xử lý là TRƯỚC, thì nó có thể xử lý lỗi và cho phép .then()
trình xử lý vẫn được gọi.
Khi nào sử dụng cái nào:
Sử dụng lược đồ đầu tiên nếu bạn chỉ muốn một .catch()
trình xử lý có thể bắt lỗi trong lời hứa ban đầu p
hoặc trong .then()
trình xử lý và từ chối từ p
sẽ bỏ qua .then()
trình xử lý.
Sử dụng lược đồ thứ hai nếu bạn muốn có thể bắt lỗi trong lời hứa ban đầu p
và có thể (tùy thuộc vào điều kiện), cho phép chuỗi hứa tiếp tục như đã được giải quyết, do đó thực thi .then()
trình xử lý.
Các tùy chọn khác
Có một tùy chọn khác để sử dụng cả hai lệnh gọi lại mà bạn có thể chuyển đến .then()
như trong:
p.then(fn1, fn2)
Điều này đảm bảo rằng chỉ một trong số fn1
hoặc fn2
sẽ được gọi. Nếu p
giải quyết được, sau đó fn1
sẽ được gọi. Nếu p
từ chối, sau đó fn2
sẽ được gọi. Không có sự thay đổi kết quả nào fn1
có thể làm cho fn2
được gọi hoặc ngược lại. Vì vậy, nếu bạn muốn chắc chắn rằng chỉ một trong hai trình xử lý của bạn được gọi bất kể điều gì xảy ra trong chính các trình xử lý đó thì bạn có thể sử dụng p.then(fn1, fn2)
.