Chào các bạn, hôm nay cafedev chia sẻ cho ace một danh sách các bài tập từ cơ bản tới nâng cao liên quan tới các kiến thức cơ bản trong lập trình Javascript. Cụ thể, trong bài này chúng ta sẽ làm quen với Handle Error, Promise, Async, await. Từ đó giúp ace nâng cao kiến thức, kỹ năng, kinh nghiệm lập trình của mình và áp dụng nó vào thực tế.
Trước khi đi vào chi tiết bài tập, cafedev khuyến khích ace tự code bài tập của mình trước khi tham khảo bài hướng dẫn nhé.
Để chạy hoặc code các bài tập sau, ace có thể code trên trang web này như sau:
- Chọn new
- Chọn dự án bạn muốn code, ở đây có nhiều lựa chọn như Javascript, AngularJS, React,…. Tất nhiên mình sẽ chọn Javascript.
- Sau đó bạn sẽ thấy nơi bạn code.
- Sau khi code sau chọn Preview để xem kết quả.
Ngoài ra ace cũng có thể dùng các IDE đã được giới thiệu tại đây để code và chạy code đó trên máy tính của mình nhé.
Lưu ý: Mọi bài tập bên dưới cũng như các bài tập khác trong Series Javascript này được tạo ra từ các bài học và kiến thức của từng phần trong series tự học Javascript này. Nếu ace nào chưa làm được hoặc chưa hiểu kỹ về bài học thì bạn có thể tham khảo lại series tự học này nhé. Chúc các bạn thành công.
Bài 1
So sánh hai đoạn code.
- Cái đầu tiên sử dụng
finally
để thực thi mã sau khitry..catch
:
try {
work work
} catch (e) {
handle errors
} finally {
cleanup the working space
}
2. Đoạn thứ hai đặt quá trình dọn dẹp ngay sau khi try..catch
:
try {
work work
} catch (e) {
handle errors
}
cleanup the working space
Chúng ta chắc chắn cần dọn dẹp sau khi làm việc, không quan trọng có lỗi hay không.
Có một lợi thế ở đây trong việc sử dụng cuối cùng hay cả hai đoạn code đều bằng nhau? Nếu có một lợi thế như vậy, sau đó đưa ra một ví dụ khi nó quan trọng.
Bài 2
Tạo một lớp FormatError kế thừa từ lớp SyntaxError dựng sẵn.
Nó phải hỗ trợ các thuộc tính message
, name
và stack
Ví dụ sử dụng:
let err = new FormatError("formatting error");
alert( err.message ); // formatting error
alert( err.name ); // FormatError
alert( err.stack ); // stack
alert( err instanceof FormatError ); // true
alert( err instanceof SyntaxError ); // true (because inherits from SyntaxError)
Giải bài 1,2
Bài 3
Tạo một hàm showCircle (cx, cy, radius) hiển thị một vòng tròn đang phát triển lớn dần với animation.
cx, cy là tọa độ tương đối cửa sổ của tâm hình tròn,radius
là bán kính của hình tròn
Đây là code ví dụ về cách vẽ hình tròn với animation khi hình tròn lớn dần.
ví dụ
Bây giờ, giả sử chúng ta không chỉ cần một hình tròn mà còn cần hiển thị một thông điệp bên trong nó. Thông báo sẽ xuất hiện sau khi animation của hình tròn hoàn tất (hình tròn đã phát triển hoàn toàn), nếu không, nó sẽ trông khó nhìn.
Bài 4
Đầu ra của đoạn code dưới đây là gì?
let promise = new Promise(function(resolve, reject) {
resolve(1);
setTimeout(() => resolve(2), 1000);
});
promise.then(alert);
Bài 5
Hàm setTimeout tích hợp sẵn để sử dụng các lệnh gọi lại. Tạo một giải pháp thay thế dựa trên lời hứa(promise).
Hàm delay(ms)
sẽ trả về một lời hứa. Lời hứa đó sẽ giải quyết sau mili giây, để chúng ta có thể thêm .then vào nó, như thế này:
function delay(ms) {
// your code
}
delay(3000).then(() => alert('runs after 3 seconds'));
Bài 6
Viết lại hàm showCircle trong trong bài tập 3 để nó trả về một lời hứa thay vì chấp nhận một lệnh gọi lại.
showCircle(150, 150, 100).then(div => {
div.classList.add('message-ball');
div.append("Hello, world!");
});
Bài giải 3,4,5,6
Bài 7
Các đoạn code này có bằng nhau không? Nói cách khác, chúng có hoạt động giống nhau trong bất kỳ trường hợp nào, đối với bất kỳ hàm xử lý nào không?
promise.then(f1).catch(f2);
Đấu với:
promise.then(f1, f2);
Bài 8
Bạn nghĩ sao? .Catch sẽ kích hoạt? Giải thich câu trả lơi của bạn.
new Promise(function(resolve, reject) {
setTimeout(() => {
throw new Error("Whoops!");
}, 1000);
}).catch(alert);
Bài 9
Viết lại code ví dụ này và sử dụng async / await thay vì .then / catch:
function loadJson(url) {
return fetch(url)
.then(response => {
if (response.status == 200) {
return response.json();
} else {
throw new Error(response.status);
}
})
}
loadJson('no-such-user.json')
.catch(alert); // Error: 404
Bài 10
Dưới đây, bạn có thể tìm thấy ví dụ “rethrow” từ chuỗi chuỗi Hứa hẹn. Viết lại nó bằng cách sử dụng async / await thay vì .then / catch.
Và loại bỏ đệ quy bằng một vòng lặp trong demoGithubUser: với async / await, điều đó trở nên dễ dàng thực hiện.
class HttpError extends Error {
constructor(response) {
super(`${response.status} for ${response.url}`);
this.name = 'HttpError';
this.response = response;
}
}
function loadJson(url) {
return fetch(url)
.then(response => {
if (response.status == 200) {
return response.json();
} else {
throw new HttpError(response);
}
})
}
// Ask for a user name until github returns a valid user
function demoGithubUser() {
let name = prompt("Enter a name?", "iliakan");
return loadJson(`https://api.github.com/users/${name}`)
.then(user => {
alert(`Full name: ${user.name}.`);
return user;
})
.catch(err => {
if (err instanceof HttpError && err.response.status == 404) {
alert("No such user, please reenter.");
return demoGithubUser();
} else {
throw err;
}
});
}
demoGithubUser();
Bài 11
Chúng ta có một hàm “thông thường”. Làm thế nào để gọi async từ nó và sử dụng kết quả của nó?
async function wait() {
await new Promise(resolve => setTimeout(resolve, 1000));
return 10;
}
function f() {
// ...what to write here?
// we need to call async wait() and wait to get 10
// remember, we can't use "await"
}
P.S. Về mặt kỹ thuật, nhiệm vụ này rất đơn giản, nhưng câu hỏi này khá phổ biến đối với các nhà phát triển mới làm quen với async / await.
Bài giải 7,8,9,10,11
Nguồn và Tài liệu tiếng anh tham khảo:
Tài liệu từ cafedev:
- Full series tự học Javascript từ cơ bản tới nâng cao tại đây nha.
- Ebook về javascript tại đây.
- Các series tự học lập trình khác
Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:
Chào thân ái và quyết thắng!