Menu
CoddyTech

Bộ hẹn giờ

Thuộc phần Kiến thức cơ bản về Node.js trong hành trình Node.js của Coddy. Bài học 27 trên 33.

Một lời nhắc nên đếm ngược trên màn hình, từng bước một, rồi dừng lại.

setInterval(fn, ms) chạy fn sau mỗi ms mili giây cho đến khi clearInterval(id) dừng nó; setTimeout chỉ chạy một lần. Chương trình chỉ kết thúc khi không còn bộ hẹn giờ nào, vì vậy một vòng lặp mà bạn không bao giờ xóa sẽ khiến chương trình tiếp tục chạy.

let lap = 1;
const id = setInterval(() => {
    console.log(`Lap ${lap}`);
    lap += 1;
    if (lap > 3) {
        clearInterval(id);
    }
}, 500);

Terminal dừng chương trình sau 5 giây, nhờ đó bạn nhận ra mình đã quên clearInterval.

challenge icon

Thử thách

Dễ

Bộ hẹn giờ đếm ngược trên màn hình rồi mới hiển thị ghi chú. Thêm lệnh remind để làm việc này bằng bộ hẹn giờ.

  1. Trong notes.js, thêm lệnh remind. Từ đứng sau lệnh này là số thứ tự của ghi chú, được kiểm tra giống như trong done, nên bạn có thể dùng lại noteNumber.
  2. Bắt đầu một setInterval với độ trễ 200 mili giây. Mỗi nhịp in ra một dòng: trước tiên là 3, rồi 2, tiếp theo là 1, cuối cùng là nội dung ghi chú.
  3. Sau khi in ghi chú, dừng khoảng lặp bằng clearInterval để chương trình kết thúc.

Với các ghi chú Buy milk và Call Ada, lệnh node notes.js remind 2 in ra các dòng sau, mỗi dòng cách nhau 200 mili giây:

3
2
1
Call Ada
  1. Số không phải số thứ tự của ghi chú sẽ gây lỗi giống như trong done. Với hai ghi chú, lệnh node notes.js remind 9 in No note 9 ra stderr rồi thoát với mã 1, mà không đếm ngược.

Thử nhé: nhập remind 1 vào ô sau $ node notes.js rồi nhấn Enter. Bạn sẽ thấy phần đếm ngược, sau đó là ghi chú đầu tiên. Tiếp theo, nhập remind 9: bạn sẽ thấy No note 9 màu đỏ và mã thoát 1. Nếu quên clearInterval, chương trình sẽ không tự kết thúc và terminal sẽ dừng chương trình sau 5 giây.

Tự làm thử

// Công cụ ghi chú của bạn bắt đầu từ đây.
import { rmSync } from 'node:fs';
import path from 'node:path';
import { formatNote } from './format.js';
import stats from './legacy/stats.cjs';
import store from './store.js';

const [command, ...words] = process.argv.slice(2);
const text = words.join(' ');

const noteNumber = (word) => {
    const n = Number(word);
    if (!Number.isInteger(n) || n < 1 || n > store.notes.length) {
        console.error(`No note ${word}`);
        process.exit(1);
    }
    return n;
};

if (command === 'add') {
    const n = await store.add(text);
    console.log(`Saved note ${n}.`);
} else if (command === 'list') {
    const owner = process.env.NOTES_OWNER ?? 'you';
    console.log(`Notes for ${owner}`);
    if (store.notes.length === 0) {
        console.log('No notes yet');
    }
    const lines = store.notes.map((note, i) => formatNote(i + 1, note));
    if (store.settings.sort === 'newest') {
        lines.reverse();
    }
    lines.forEach((line) => console.log(line));
} else if (command === 'where') {
    const file = path.join(process.cwd(), 'notes.json');
    console.log(file);
    console.log(path.basename(file));
} else if (command === 'stats') {
    console.log(`${store.notes.length} notes, ${stats.countWords(store.notes)} words`);
} else if (command === 'done') {
    const removed = await store.remove(noteNumber(words[0]));
    console.log(`Done: ${removed}`);
} else if (command === 'clear') {
    rmSync('notes.json', { force: true });
    console.log('Deleted notes.json');
} else {
    if (command) {
        console.error(`Unknown command: ${command}`);
    }
    console.error('Usage: node notes.js <command> [words]');
    process.exit(1);
}

Tất cả bài học trong Kiến thức cơ bản về Node.js

Tự luyện tập: Playground Express