Bài này biên về Promise, khá phức tạp, nếu chưa hiểu các bạn có thể in ra đem vào để trong toilet, mổi lần vào đó thì cầm lên đọc giết thời gian. Mình đã làm và thành công, nhất là những hôm táo bón. Có khi đọc nhập tâm quá chui ngược vào. Không biết có phải là hiện tượng phản phác quy chân ko nữa. ahihi.
Ghi chú:
Nếu tên function là dạng tiếng mẻo, thì mình sẽ viết camelCase, vd: doSomething()
Nếu tên function là tiếng việt ko dấu, để dễ đọc mình sẽ viết underscore, vd: dung_khoc_ma_vui_cuoi_len()
Các bạn code kiểu gì thì code, quan trọng là nhất quán, dùng 1 style thôi, đừng như mình !
Bắt đầu chém gió thôi:
Ai cũng từng 1 lần cho bạn mượn tiền, có đứa hứa sẽ trả (pending), có đứa trả (fulfilled), và cũng có đứa một đi không trở lại (reject).
Đây cũng 3 trạng thái của Promise.
Khi 1 function đang kẹt nhưng hứa sẽ trả tiền cho chúng ta vào 1 tương lai xa. Nhưng chúng ta lại cần dùng số tiền đó trong 1 function khác. Khi đấy Promise sẽ đóng vai trò là giá trị chúng ta cần, để chúng ta có thể gán nợ ngay, mà ko cần đợi thằng kia trả tiền.
Lúc này anh em cứ nghĩ Promise là 1 tờ giấy lộn, nhưng có tác dụng thật, là minh chứng (proxy) cho cục tiền nợ có nguy cơ mất 99% kia.
tra_tien_em_anh_oi() // trả về 1 Promise.
.then(function(tien) {
// chúng ta có thể làm gì đó với số tiền này ngay lập tức
// ơ làm gì đây
return nhau_an_mung(tien);
})
.catch(function(ly_do_quit){
console.log(ly_do_quit);
})
tra_tien_em_anh_oi()
sẽ ko phun ra xu nào, mà chỉ trả về tờ giấy nợ Promise. Tạm thời chưa nói đến cách tạo. Anh em chú ý thằng .then
và .catch
đây là 2 method của Promise.prototype, chỉ gọi dc khi new Promise lên.
Nếu chưa biết prototype là gì thì anh em tham khảo bài biên này http://kipalog.com/posts/prototype-la-khi-gi-
Con hàng này dc gọi khi Promise resolve, tất nhiên khi đấy chúng ta sẽ lấy dc tiền, và làm gì với số tiền đó là tuỳ chúng ta.
Muốn .then
nhiều lần cũng dc, khi đấy Promise sẽ thực hiện các function trong .then
theo thứ tự. Tụi mẻo gọi vụ này là Chaining. Đây là lý do nhiều ng thích Promise, vì nó giúp chúng ta tổ chức và code rất kotex.
tra_tien_em_anh_oi()
.then(function(tien) {
return nhau_an_mung(tien);
})
.then(function(tien_con_lai_sau_khi_nhau){
return mat_xa(tien_con_lai_sau_khi_nhau);
})
.then(function(){ // het tien
return hue_oi();
});
Lưu ý trong cái .then
thứ 2, giá trịtien_con_lai_sau_khi_nhau
là kết quả của function nhau_an_mung
, sau đó tiền, à ko có sau đó nữa vì đã hết tiền, .then
cuối cùng ko có giá trị gì truyền vào cả !
Anh em cũng chú ý là .then
sẽ nhận vào 1 function, nếu chọi cái khác vào, tuy nó cho phép chúng ta có quyền im lặng .then(null)
nhưng những gì chúng ta nói, nó sẽ coi như chưa nói gì cả. Ngay cả truyền 1 Promise cho nó, nó cũng lơ luôn. Ăn có thể ăn bậy, nhưng nói không thể nói bậy. Luôn truyền cho .then một function nhoé.
Và nhớ return, return 1 Promise khác cũng dc, mà 1 giá trị tuỳ ý cũng dc. Cái này anh em cứ buông tay tuỳ tiện mà làm. Ngay cả return null cũng viết vào luôn, cho nó rõ ràng.
Trong trường hợp tra_tien_em_anh_oi
ko trả tiền, tức là Promise bị reject, thì con hàng này sẽ chạy, tất nhiên là ko có tiền, nhưng chúng ta sẽ nhận dc lý do quịt nợ một cách lịch sự, có thể chỉ là 1 string, hoặc cũng có thể là 1 exception. Nói chung chúng ta sẽ có lý do, để còn báo cáo lại cho quan bà ở nhà.
Promise ưu việt hơn callback ở chổ chúng ta có thể khạc nhổ exception một cách bừa bãi mà ko lo lắng vì .catch
sẽ lụm dc hết.**
function tra_tien_em_anh_oi() {
// tạo và trả về 1 Promise, khi này Promise ở trang thái pending
return new Promise(function(resolve, reject) {
// tâm sinh lý ngẫu nhiên
var isHappy = Math.random() >= 0.5;
// nếu vui thì gọi resolve để trả tiền
if (isHappy) {
var tien = 1000;
return resolve(tien); // Promise dc fulfilled
}
// không vui quịt luôn
// nhớ cho ng ta biết lý do vì chúng ta là lập trình viên lịch sự.
var reason = 'lịt pẹ bố dek trả đấy làm gì nhau';
reject(reason); // Promise ở trạng thái reject
});
}
Tuy nói Promise giúp tổ chức code, và tránh callback hell, nhưng nếu viết code ko khô thoáng và sạch sẽ thì anh em vẫn rơi vào Promise Hell. Do đó lúc nào chúng ta cũng phải dùng kotexcode.
Promise Hell vì nested .then
ngu.
tra_tien_em_anh_oi()
.then(function(tien){
return nhau_an_mung(tien)
.then(function(tien_con_lai){
return mat_xa(tien_con_lai)
.then(function(){
return hue_oi();
})
})
})
tra_tien_em_anh_oi()
.then(nhau_an_mung)
.then(mat_xa)
.catch(console.error.bind(console));
Sau đây là kinh nguyệt và các tâm đắc khi dùng Promise, anh em có thể tham khảo và góp ý hộ iem.
// code sync
function nhau_an_mung() {
return 500;
}
// wrap lại bằng Promise
function nhau_an_mung() {
return Promise.resolve(500);
}
ve_nha
, chỉ chạy khi đã uong_ruou
và hut_thuoc
, mà 2 sở thích đời thường này lại có thể cùng lúc tiến hành. Cho nhanh chết.
// thay vì
e_nhau_khong()
.then(uong_ruou)
.then(hut_thuoc)
.then(ve_nha)
.catch(console.log);
// nên viết thế này
e_nhau_khong()
.then(function(){
return Promise.all([
uong_ruou(),
hut_thuoc()
])
})
.then(ve_nha)
.catch(console.error.bind(console));
Cách viết đầu tiên chậm vì muốn đốt điếu thuốc phải ráng nhịn đến khi tàn cuộc nhậu, tỉ dụ uong_ruou cần 1 tiếng, hut_thuoc cũng 1 tiếng thì ta cần 2 tiếng mới về đến nhà.
Cách viết thứ 2 dùng Promise.all
code chạy nhanh gấp nhiều lần so với cách 1 vì uong_ruou và hut_thuoc sẽ dc chạy song song, cùng lúc ( parallel ) nên chỉ tốn 1 tiếng là đã xong. Nhanh gấp đôi.
Kinh nguyệt là cái gì chạy parallel dc thì cho chạy parallel hết. Tốc độ cải thiện rất vi diệu !
Anh em nghe mùi chắc cũng biết nested .then
function findMoney()
.then(function(money){
// findMoney trả về .. money
// truyền money vào findCard để chuộc thẻ sinh viên
return findCard(money)
.then(function(card){
// có thẻ thì đi thư viện tìm sách
return findBooks(money, card) // findBooks cần tiền và sách từ các Promise trên
.then(function(books){
// lựa sách 18+ đọc thôi
return readEpicBooks(books.filter(function(book){
return !! (book.categoryName === '18+');
}));
});
});
})
.catch(console.error.bind(console));
Trường hợp như trên nested .then
hơi khó tránh tuy nhiên muốn tránh vẫn có nhiều cách, ví dụ như dùng scope chẳng hạn.
Anh em nào chưa biết scope thì xem ở đây http://kipalog.com/posts/scope-va-closure-la-khi-gi-
var money
findMoney()
.then(function(_money){
money = _money;
return findCard(money);
})
.then(function(card){
return findBook(money, card);
})
// .....
Hoặc cũng có thể dùng Promise.all
var money = findMoney();
var card = moneyPromise.then(findCard);
Promise.all([money, card])
.then(function(res){
return findBooks(res[0], res[1]);
})
.then(console.log.bind(console))
.catch(console.error.bind(console))
Có điều nếu chỉ nested .then
1 cấp thì cũng ko cần phải tự tay bóp dái chi cho đau. Kinh nguyệt là tuỳ trường hợp nếu thấy rối và khó đọc thì chúng ta mới cần refactore.
Promise.resolve('em xin hết ạ');
à mà quên, câu hỏi có trúng chưởng:
Code sau đây ngu ở chổ nào, hãy đưa ra 10 lý do chứng minh quocnguyen đẹp trai.
doSomething().then(function () {
doSomethingElse();
});
source: https://kipalog.com/posts/Promise-la-khi-gi-
You need to login in order to like this post: click here
YOU MIGHT ALSO LIKE