Hứa có trạng thái, chúng bắt đầu như đang chờ xử lý và có thể giải quyết:
- hoàn thành nghĩa là tính toán hoàn thành thành công.
- từ chối có nghĩa là tính toán thất bại.
Các hàm trả về hứa sẽ không bao giờ ném , thay vào đó chúng nên trả về các từ chối. Ném từ hàm trả về lời hứa sẽ buộc bạn sử dụng cả a } catch {
và a .catch
. Những người sử dụng API được quảng cáo không mong đợi những lời hứa sẽ ném. Nếu bạn không chắc chắn cách API async hoạt động trong JS - vui lòng xem câu trả lời này trước.
1. Tải DOM hoặc sự kiện một lần khác:
Vì vậy, tạo lời hứa thường có nghĩa là chỉ định khi họ giải quyết - điều đó có nghĩa là khi họ chuyển sang giai đoạn hoàn thành hoặc bị từ chối để cho biết dữ liệu có sẵn (và có thể được truy cập cùng .then
).
Với các triển khai lời hứa hiện đại hỗ trợ nhà Promise
xây dựng như lời hứa ES6 bản địa:
function load() {
return new Promise(function(resolve, reject) {
window.onload = resolve;
});
}
Sau đó, bạn sẽ sử dụng lời hứa kết quả như vậy:
load().then(function() {
// Do things after onload
});
Với các thư viện hỗ trợ hoãn lại (Hãy sử dụng $ q cho ví dụ này tại đây, nhưng chúng tôi cũng sẽ sử dụng jQuery sau):
function load() {
var d = $q.defer();
window.onload = function() { d.resolve(); };
return d.promise;
}
Hoặc với một API như jQuery, nối vào một sự kiện xảy ra một lần:
function done() {
var d = $.Deferred();
$("#myObject").once("click",function() {
d.resolve();
});
return d.promise();
}
2. Gọi lại đơn giản:
Các API này khá phổ biến vì các cuộc gọi lại cũng rất phổ biến trong JS. Hãy xem xét trường hợp phổ biến của việc có onSuccess
và onFail
:
function getUserData(userId, onLoad, onFail) { …
Với các triển khai lời hứa hiện đại hỗ trợ nhà Promise
xây dựng như lời hứa ES6 bản địa:
function getUserDataAsync(userId) {
return new Promise(function(resolve, reject) {
getUserData(userId, resolve, reject);
});
}
Với các thư viện hỗ trợ hoãn lại (Hãy sử dụng jQuery cho ví dụ này tại đây, nhưng chúng tôi cũng đã sử dụng $ q ở trên):
function getUserDataAsync(userId) {
var d = $.Deferred();
getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
return d.promise();
}
jQuery cũng cung cấp một $.Deferred(fn)
biểu mẫu, có lợi thế là cho phép chúng ta viết một biểu thức mô phỏng rất chặt chẽ new Promise(fn)
biểu mẫu, như sau:
function getUserDataAsync(userId) {
return $.Deferred(function(dfrd) {
getUserData(userId, dfrd.resolve, dfrd.reject);
}).promise();
}
Lưu ý: Ở đây chúng tôi khai thác thực tế là các phương thức resolve
và reject
phương thức trì hoãn của jQuery là "có thể tháo rời"; I E. chúng bị ràng buộc với thể hiện của jQuery.Deferred (). Không phải tất cả các lib đều cung cấp tính năng này.
3. Gọi lại kiểu nút ("gật đầu"):
Các cuộc gọi lại kiểu nút (nút bấm) có một định dạng cụ thể trong đó các cuộc gọi lại luôn là đối số cuối cùng và tham số đầu tiên của nó là một lỗi. Trước tiên hãy quảng cáo một cách thủ công:
getStuff("dataParam", function(err, data) { …
Đến:
function getStuffAsync(param) {
return new Promise(function(resolve, reject) {
getStuff(param, function(err, data) {
if (err !== null) reject(err);
else resolve(data);
});
});
}
Với việc trì hoãn, bạn có thể thực hiện các thao tác sau (hãy sử dụng Q cho ví dụ này, mặc dù hiện tại Q hỗ trợ cú pháp mới mà bạn nên chọn ):
function getStuffAsync(param) {
var d = Q.defer();
getStuff(param, function(err, data) {
if (err !== null) d.reject(err);
else d.resolve(data);
});
return d.promise;
}
Nói chung, bạn không nên quảng cáo mọi thứ theo cách thủ công quá nhiều, hầu hết các thư viện hứa hẹn được thiết kế với Node cũng như các lời hứa riêng trong Node 8+ đều có phương pháp tích hợp để quảng cáo các nút bấm. Ví dụ
var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only
4. Toàn bộ thư viện với các cuộc gọi lại kiểu nút:
Không có quy tắc vàng ở đây, bạn hứa hẹn từng cái một. Tuy nhiên, một số triển khai lời hứa cho phép bạn thực hiện hàng loạt việc này, ví dụ như trong Bluebird, chuyển đổi API gật đầu thành API hứa hẹn cũng đơn giản như:
Promise.promisifyAll(API);
Hoặc với những lời hứa riêng trong Node :
const { promisify } = require('util');
const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)}))
.reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});
Ghi chú:
- Tất nhiên, khi bạn ở trong một người
.then
xử lý, bạn không cần phải quảng bá mọi thứ. Trả lại lời hứa từ người .then
xử lý sẽ giải quyết hoặc từ chối với giá trị của lời hứa đó. Ném từ một người .then
xử lý cũng là một thực hành tốt và sẽ từ chối lời hứa - đây là lời hứa ném an toàn nổi tiếng.
- Trong
onload
trường hợp thực tế , bạn nên sử dụng addEventListener
chứ không phải onX
.