Một
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
2 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ì hầu hết mọi người là người tiêu dùng của những lời hứa đã được tạo, hướng dẫn này sẽ giải thích việc tiêu thụ những lời hứa được trả lại trước khi giải thích cách tạo chúngVề cơ bản, một lời hứa là một đối tượng được trả về mà bạn đính kèm các cuộc gọi lại, thay vì chuyển các cuộc gọi lại vào một hàm. Hãy tưởng tượng một chức năng,
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
3, tạo ra một tệp âm thanh không đồng bộ với một bản ghi cấu hình và hai chức năng gọi lại. một được gọi nếu tệp âm thanh được tạo thành công và một được gọi nếu xảy ra lỗiĐây là một số mã sử dụng
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
3function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
Nếu
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
3 được viết lại để trả lại một lời hứa, thay vào đó, bạn sẽ đính kèm các lệnh gọi lại của mình vào đócreateAudioFileAsync[audioSettings].then[successCallback, failureCallback];
Quy ước này có một số lợi thế. Chúng ta sẽ khám phá từng cái một
xiềng xích
Một nhu cầu phổ biến là thực hiện hai hoặc nhiều hoạt động không đồng bộ quay lại, trong đó mỗi hoạt động tiếp theo bắt đầu khi hoạt động trước đó thành công, với kết quả từ bước trước đó. Ngày xưa, thực hiện một số hoạt động không đồng bộ liên tiếp sẽ dẫn đến kim tự tháp gọi lại cổ điển của sự diệt vong
doSomething[function [result] {
doSomethingElse[result, function [newResult] {
doThirdThing[newResult, function [finalResult] {
console.log[`Got the final result: ${finalResult}`];
}, failureCallback];
}, failureCallback];
}, failureCallback];
Với những lời hứa, chúng tôi thực hiện điều này bằng cách tạo một chuỗi lời hứa. Thiết kế API của các lời hứa làm cho điều này trở nên tuyệt vời, bởi vì các cuộc gọi lại được đính kèm với đối tượng lời hứa được trả về, thay vì được chuyển vào một hàm
Đây là điều kỳ diệu. hàm
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
6 trả về một lời hứa mới, khác với lời hứa ban đầuconst promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
Lời hứa thứ hai này [
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
7] thể hiện sự hoàn thành không chỉ của const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
8, mà còn của const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
9 hoặc const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
20 mà bạn đã chuyển vào — có thể là các hàm không đồng bộ khác trả về một lời hứa. Trong trường hợp đó, bất kỳ cuộc gọi lại nào được thêm vào const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
7 sẽ được xếp hàng sau lời hứa được trả về bởi const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
9 hoặc const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
20Với mẫu này, bạn có thể tạo các chuỗi xử lý dài hơn, trong đó mỗi lời hứa thể hiện việc hoàn thành một bước không đồng bộ trong chuỗi. Ngoài ra, các đối số của
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
24 là tùy chọn và const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
25 là viết tắt của const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
26 — vì vậy nếu mã xử lý lỗi của bạn giống nhau cho tất cả các bước, bạn có thể đính kèm mã đó vào cuối chuỗiconst promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
2Thay vào đó, bạn có thể thấy điều này được thể hiện bằng các hàm mũi tên
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
0Quan trọng. Luôn trả về kết quả, nếu không, các cuộc gọi lại sẽ không bắt được kết quả của lời hứa trước đó [với các chức năng mũi tên,
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
27 là viết tắt của const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
28]. Nếu người xử lý trước đó đã bắt đầu một lời hứa nhưng không trả lại, thì không có cách nào để theo dõi việc giải quyết của nó nữa và lời hứa được cho là "thả nổi"const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
3Điều này có thể tồi tệ hơn nếu bạn có điều kiện chủng tộc — nếu lời hứa từ trình xử lý cuối cùng không được trả lại, trình xử lý
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
24 tiếp theo sẽ được gọi sớm và mọi giá trị mà nó đọc có thể không đầy đủconst promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
5Do đó, theo nguyên tắc thông thường, bất cứ khi nào hoạt động của bạn gặp phải một lời hứa, hãy trả lại nó và hoãn việc xử lý nó cho trình xử lý
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
24 tiếp theoconst promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
7làm tổ
Trong hai ví dụ trên, ví dụ đầu tiên có một chuỗi lời hứa được lồng trong giá trị trả về của một trình xử lý
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
6 khác, trong khi ví dụ thứ hai sử dụng một chuỗi phẳng hoàn toàn. Các chuỗi lời hứa đơn giản tốt nhất nên được giữ phẳng mà không cần lồng vào nhau, vì việc lồng vào nhau có thể là kết quả của thành phần bất cẩn. Xem những lỗi thường gặpNesting là một cấu trúc điều khiển để giới hạn phạm vi của các câu lệnh
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
02. Cụ thể, một const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
02 lồng nhau chỉ phát hiện lỗi trong phạm vi của nó và bên dưới, không phát hiện lỗi cao hơn trong chuỗi bên ngoài phạm vi lồng nhau. Khi được sử dụng đúng cách, điều này mang lại độ chính xác cao hơn trong việc khôi phục lỗifunction successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
1Lưu ý rằng các bước tùy chọn ở đây được lồng vào nhau — với việc lồng vào nhau không phải do vết lõm, mà do vị trí của dấu ngoặc đơn
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
04 và const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
05 bên ngoài xung quanh các bướcTrình xử lý tắt tiếng lỗi bên trong
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
02 chỉ phát hiện lỗi từ const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
07 và const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
08, sau đó mã sẽ tiếp tục với const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
09. Điều quan trọng là, nếu const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
30 không thành công, lỗi của nó chỉ được phát hiện bởi const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
02 cuối cùng [bên ngoài] và không bị nuốt bởi trình xử lý const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
02 bên trongChuỗi sau khi bắt
Có thể xâu chuỗi sau một thất bại, tôi. e. một
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
02, rất hữu ích để hoàn thành các hành động mới ngay cả sau khi một hành động không thành công trong chuỗi. Đọc ví dụ saucreateAudioFileAsync[audioSettings].then[successCallback, failureCallback];
0Điều này sẽ xuất văn bản sau
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
1Ghi chú. Văn bản "Làm điều này" không được hiển thị vì lỗi "Đã xảy ra lỗi" khiến từ chối
Lỗi thường gặp
Dưới đây là một số lỗi phổ biến cần chú ý khi soạn chuỗi lời hứa. Một số trong những sai lầm này biểu hiện trong ví dụ sau
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
2Sai lầm đầu tiên là không xâu chuỗi mọi thứ lại với nhau đúng cách. Điều này xảy ra khi chúng tôi tạo một lời hứa mới nhưng quên trả lại nó. Kết quả là chuỗi bị hỏng — hay đúng hơn là chúng ta có hai chuỗi độc lập chạy đua với nhau. Điều này có nghĩa là
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
34 sẽ không đợi const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
35 hoặc const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
36 kết thúc mà sẽ chạy song song với chúng — điều này có thể xảy ra ngoài ý muốn. Các chuỗi riêng biệt cũng có cách xử lý lỗi riêng biệt, dẫn đến các lỗi không được phát hiệnSai lầm thứ hai là lồng vào nhau một cách không cần thiết, tạo điều kiện cho sai lầm đầu tiên. Việc lồng ghép cũng giới hạn phạm vi của trình xử lý lỗi bên trong, mà—nếu ngoài ý muốn—có thể dẫn đến các lỗi chưa được phát hiện. Một biến thể của điều này là mẫu chống lại hàm tạo lời hứa, kết hợp việc lồng với việc sử dụng dự phòng của hàm tạo lời hứa để bọc mã đã sử dụng lời hứa
Sai lầm thứ ba là quên kết thúc chuỗi với
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
02. Chuỗi lời hứa chưa được kết thúc dẫn đến việc từ chối lời hứa chưa được thực hiện trong hầu hết các trình duyệt. Xem xử lý lỗi bên dướiMột nguyên tắc nhỏ là luôn trả lại hoặc chấm dứt chuỗi lời hứa và ngay khi bạn nhận được một lời hứa mới, hãy trả lại nó ngay lập tức để làm phẳng mọi thứ
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
3Lưu ý rằng
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
27 là viết tắt của const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
28Bây giờ chúng tôi có một chuỗi xác định duy nhất với việc xử lý lỗi thích hợp
Sử dụng
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
50/const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
51 giải quyết hầu hết, nếu không muốn nói là tất cả những vấn đề này — sự đánh đổi là có thể dễ dàng quên từ khóa const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
51xử lý lỗi
Bạn có thể nhớ đã nhìn thấy
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
20 ba lần trong kim tự tháp diệt vong trước đó, so với chỉ một lần ở cuối chuỗi lời hứacreateAudioFileAsync[audioSettings].then[successCallback, failureCallback];
4Nếu có ngoại lệ, trình duyệt sẽ tìm xuống chuỗi để tìm trình xử lý
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
54 hoặc const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
55. Điều này được mô hình hóa rất nhiều sau cách thức hoạt động của mã đồng bộcreateAudioFileAsync[audioSettings].then[successCallback, failureCallback];
5Sự đối xứng này với mã không đồng bộ lên đến đỉnh điểm trong cú pháp
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
50/const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
51createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
6Nó được xây dựng dựa trên các lời hứa — ví dụ,
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
8 vẫn giữ nguyên chức năng như trước đây, do đó, chỉ cần tái cấu trúc tối thiểu để thay đổi từ các lời hứa thành const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
50/const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
51. Bạn có thể đọc thêm về cú pháp const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
50/const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
51 trong các hàm async và tài liệu tham khảo const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
51Lời hứa giải quyết một lỗ hổng cơ bản với kim tự tháp gọi lại của sự diệt vong, bằng cách bắt tất cả các lỗi, thậm chí cả các ngoại lệ bị ném và lỗi lập trình. Điều này là cần thiết cho thành phần chức năng của các hoạt động không đồng bộ
Sự kiện từ chối lời hứa
Nếu một sự kiện từ chối lời hứa không được xử lý bởi bất kỳ trình xử lý nào, nó sẽ nổi lên trên cùng của ngăn xếp cuộc gọi và máy chủ lưu trữ cần hiển thị nó. Trên web, bất cứ khi nào một lời hứa bị từ chối, một trong hai sự kiện sẽ được gửi đến phạm vi toàn cầu [thông thường, đây là
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
74 hoặc, nếu được sử dụng trong nhân viên web, đó là const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
75 hoặc giao diện dựa trên nhân viên khác]. Hai sự kiện làconst promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
76Được gửi khi một lời hứa bị từ chối nhưng không có sẵn trình xử lý từ chối
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
77Được gửi khi một trình xử lý được đính kèm với một lời hứa bị từ chối đã gây ra sự kiện
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
76Trong cả hai trường hợp, sự kiện [thuộc loại
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
79] có các thành viên thuộc tính function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
10 cho biết lời hứa đã bị từ chối và thuộc tính function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
11 cung cấp lý do cho lời hứa bị từ chốiNhững điều này có thể cung cấp khả năng xử lý lỗi dự phòng cho các lời hứa, cũng như giúp gỡ lỗi các vấn đề với quản lý lời hứa của bạn. Các trình xử lý này là toàn cầu theo ngữ cảnh, vì vậy tất cả các lỗi sẽ chuyển đến cùng một trình xử lý sự kiện, bất kể nguồn
trong nút. js, việc xử lý từ chối lời hứa hơi khác một chút. Bạn nắm bắt các từ chối chưa được xử lý bằng cách thêm trình xử lý cho Nút. js sự kiện
function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
12 [chú ý sự khác biệt trong cách viết hoa của tên], như thế nàycreateAudioFileAsync[audioSettings].then[successCallback, failureCallback];
7Đối với nút. js, để ngăn lỗi được ghi vào bảng điều khiển [hành động mặc định sẽ xảy ra], việc thêm trình nghe
function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
13 đó là tất cả những gì cần thiết; Tuy nhiên, nếu bạn thêm trình nghe
function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
15 đó nhưng cũng không có mã bên trong để xử lý các lời hứa bị từ chối, chúng sẽ bị loại bỏ và bị bỏ qua một cách im lặng. Vì vậy, lý tưởng nhất là bạn nên thêm mã trong trình nghe đó để kiểm tra từng lời hứa bị từ chối và đảm bảo rằng nó không phải do lỗi mã thực sự gây raThành phần
Có bốn công cụ tổng hợp để chạy đồng thời các hoạt động không đồng bộ.
function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
16, function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
17, function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
18 và function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
19Chúng ta có thể bắt đầu hoạt động song song và đợi tất cả chúng kết thúc như thế này
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
8Nếu một trong những lời hứa trong mảng bị từ chối,
function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
16 ngay lập tức từ chối lời hứa được trả lại và hủy bỏ các hoạt động khác. Điều này có thể gây ra trạng thái hoặc hành vi không mong muốn. function successCallback[result] {
console.log[`Audio file ready at URL: ${result}`];
}
function failureCallback[error] {
console.error[`Error generating audio file: ${error}`];
}
createAudioFileAsync[audioSettings, successCallback, failureCallback];
17 là một công cụ tổng hợp khác đảm bảo tất cả các hoạt động được hoàn thành trước khi giải quyếtTất cả các phương thức này đều chạy song song các lời hứa — một chuỗi các lời hứa được bắt đầu đồng thời và không đợi nhau. Thành phần tuần tự có thể sử dụng một số JavaScript thông minh
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
9Trong ví dụ này, chúng tôi rút gọn một mảng các hàm không đồng bộ thành một chuỗi lời hứa. Đoạn mã trên tương đương với
doSomething[function [result] {
doSomethingElse[result, function [newResult] {
doThirdThing[newResult, function [finalResult] {
console.log[`Got the final result: ${finalResult}`];
}, failureCallback];
}, failureCallback];
}, failureCallback];
0Điều này có thể được tạo thành một chức năng soạn thảo có thể tái sử dụng, phổ biến trong lập trình chức năng
doSomething[function [result] {
doSomethingElse[result, function [newResult] {
doThirdThing[newResult, function [finalResult] {
console.log[`Got the final result: ${finalResult}`];
}, failureCallback];
}, failureCallback];
}, failureCallback];
1Hàm
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
02 chấp nhận bất kỳ số lượng hàm nào làm đối số và trả về một hàm mới chấp nhận một giá trị ban đầu được chuyển qua đường ống thành phầndoSomething[function [result] {
doSomethingElse[result, function [newResult] {
doThirdThing[newResult, function [finalResult] {
console.log[`Got the final result: ${finalResult}`];
}, failureCallback];
}, failureCallback];
}, failureCallback];
2Bố cục tuần tự cũng có thể được thực hiện ngắn gọn hơn với async/await
doSomething[function [result] {
doSomethingElse[result, function [newResult] {
doThirdThing[newResult, function [finalResult] {
console.log[`Got the final result: ${finalResult}`];
}, failureCallback];
}, failureCallback];
}, failureCallback];
3Tuy nhiên, trước khi bạn soạn các lời hứa một cách tuần tự, hãy cân nhắc xem điều đó có thực sự cần thiết hay không — tốt hơn hết là chạy các lời hứa song song để chúng không chặn lẫn nhau một cách không cần thiết trừ khi việc thực hiện một lời hứa phụ thuộc vào kết quả của một lời hứa khác
Tạo một Lời hứa xung quanh API gọi lại cũ
Một
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
2 có thể được tạo từ đầu bằng hàm tạo của nó. Điều này chỉ cần thiết để bọc các API cũTrong một thế giới lý tưởng, tất cả các chức năng không đồng bộ sẽ trả về lời hứa. Thật không may, một số API vẫn mong đợi các cuộc gọi lại thành công và/hoặc thất bại được chuyển theo cách cũ. Ví dụ rõ ràng nhất là hàm
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
04doSomething[function [result] {
doSomethingElse[result, function [newResult] {
doThirdThing[newResult, function [finalResult] {
console.log[`Got the final result: ${finalResult}`];
}, failureCallback];
}, failureCallback];
}, failureCallback];
4Trộn các cuộc gọi lại và lời hứa kiểu cũ là vấn đề. Nếu
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
05 bị lỗi hoặc có lỗi lập trình, không có gì bắt được nó. Đây là bản chất của thiết kế của createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
06May mắn thay, chúng ta có thể gói gọn
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
06 trong một lời hứa. Cách tốt nhất là bọc các chức năng chấp nhận gọi lại ở mức thấp nhất có thể và sau đó không bao giờ gọi lại chúng trực tiếp nữadoSomething[function [result] {
doSomethingElse[result, function [newResult] {
doThirdThing[newResult, function [finalResult] {
console.log[`Got the final result: ${finalResult}`];
}, failureCallback];
}, failureCallback];
}, failureCallback];
5Hàm tạo lời hứa có chức năng thực thi cho phép chúng tôi giải quyết hoặc từ chối lời hứa theo cách thủ công. Vì
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
04 không thực sự bị lỗi, chúng tôi đã loại bỏ từ chối trong trường hợp này. Để biết thêm thông tin về cách chức năng thực thi hoạt động, hãy xem tài liệu tham khảo createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
09thời gian
Cuối cùng, chúng ta sẽ xem xét các chi tiết kỹ thuật hơn, về thời điểm cuộc gọi lại đã đăng ký được gọi
bảo lãnh
Trong API dựa trên gọi lại, thời điểm và cách thức gọi lại tùy thuộc vào trình triển khai API. Ví dụ: cuộc gọi lại có thể được gọi đồng bộ hoặc không đồng bộ
doSomething[function [result] {
doSomethingElse[result, function [newResult] {
doThirdThing[newResult, function [finalResult] {
console.log[`Got the final result: ${finalResult}`];
}, failureCallback];
}, failureCallback];
}, failureCallback];
6Điều này dẫn đến tình trạng của Zalgo, vì nó làm cho các tác dụng phụ khó phân tích
doSomething[function [result] {
doSomethingElse[result, function [newResult] {
doThirdThing[newResult, function [finalResult] {
console.log[`Got the final result: ${finalResult}`];
}, failureCallback];
}, failureCallback];
}, failureCallback];
7Mặt khác, các lời hứa là một dạng đảo ngược quyền kiểm soát - trình triển khai API không kiểm soát thời điểm cuộc gọi lại được gọi. Thay vào đó, công việc duy trì hàng đợi gọi lại và quyết định khi nào gọi các cuộc gọi lại được giao cho việc triển khai lời hứa và cả người dùng API và nhà phát triển API đều tự động nhận được các đảm bảo ngữ nghĩa mạnh mẽ, bao gồm
- Các cuộc gọi lại được thêm bằng
6 sẽ không bao giờ được gọi trước khi hoàn thành vòng chạy sự kiện JavaScript hiện tạiconst promise = doSomething[]; const promise2 = promise.then[successCallback, failureCallback];
- Các cuộc gọi lại này sẽ được gọi ngay cả khi chúng được thêm vào sau thành công hay thất bại của hoạt động không đồng bộ mà lời hứa đại diện
- Nhiều cuộc gọi lại có thể được thêm vào bằng cách gọi
6 nhiều lần. Chúng sẽ được gọi lần lượt, theo thứ tự mà chúng được chèn vàoconst promise = doSomething[]; const promise2 = promise.then[successCallback, failureCallback];
Để tránh bất ngờ, các chức năng được chuyển đến
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
6 sẽ không bao giờ được gọi đồng bộ, ngay cả với một lời hứa đã được giải quyếtdoSomething[function [result] {
doSomethingElse[result, function [newResult] {
doThirdThing[newResult, function [finalResult] {
console.log[`Got the final result: ${finalResult}`];
}, failureCallback];
}, failureCallback];
}, failureCallback];
8Thay vì chạy ngay lập tức, hàm truyền vào được đặt trong hàng đợi vi tác vụ, có nghĩa là nó chạy sau [chỉ sau khi hàm tạo ra nó thoát ra và khi ngăn xếp thực thi JavaScript trống], ngay trước khi quyền điều khiển được trả lại cho sự kiện . e. khá sớm
doSomething[function [result] {
doSomethingElse[result, function [newResult] {
doThirdThing[newResult, function [finalResult] {
console.log[`Got the final result: ${finalResult}`];
}, failureCallback];
}, failureCallback];
}, failureCallback];
9Hàng đợi nhiệm vụ so với vi nhiệm vụ
Các cuộc gọi lại lời hứa được xử lý dưới dạng một tác vụ nhỏ trong khi các cuộc gọi lại
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
04 được xử lý dưới dạng hàng đợi nhiệm vụconst promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
0Đoạn mã trên sẽ xuất ra
const promise = doSomething[];
const promise2 = promise.then[successCallback, failureCallback];
1Để biết thêm chi tiết, hãy tham khảo Nhiệm vụ so với vi nhiệm vụ
Khi lời hứa và nhiệm vụ xung đột
Nếu bạn gặp phải các tình huống trong đó bạn có các lời hứa và nhiệm vụ [chẳng hạn như các sự kiện hoặc cuộc gọi lại] đang thực hiện theo thứ tự không thể đoán trước, bạn có thể hưởng lợi từ việc sử dụng một vi tác vụ để kiểm tra trạng thái hoặc cân bằng các lời hứa của mình khi các lời hứa được tạo ra một cách có điều kiện
Nếu bạn nghĩ rằng các tác vụ vi mô có thể giúp giải quyết vấn đề này, hãy xem hướng dẫn tác vụ vi mô để tìm hiểu thêm về cách sử dụng
createAudioFileAsync[audioSettings].then[successCallback, failureCallback];
14 để liệt kê một hàm dưới dạng một tác vụ vi mô