Gần đây thấy VueJS có vẻ đang hot nên thử tìm hiểu xem thực sự nó như thế nào.
Mình cũng thử đọc code của 1 vài sample, tutorial thì thấy chỗ call API đa số đều dùng axios ở Component hay là ở bên trong Vuex.
Nếu mà áp dụng những cái đó vào trong dự án thực tế thì sẽ xảy ra những vấn đề sau:
Và còn rất nhiều vấn đề nữa…
Sau khi tìm hiểu thì mình thấy có rất nhiều design pattern có thể áp dụng cho việc gọi API. Nhưng có 1 design pattern mà mình thấy tốt nhất đó là Repository Factory.
Quả thực mình rất thích cái pattern này vì nó scale khá là dễ.
Mục đích bài viết:
Đầu tiên mình sẽ dùng repository pattern để truy cập vào tài nguyên theo cách độc lập, không có bất kì logic nào ngoài việc trả về dữ liệu.
Cái thứ 2 là sẽ sử dụng factory pattern để khởi tạo logic của môi trường hay repository cần thiết cho từng case. Factory có 1 lợi thế là có thể khởi tạo 1 mock repository hoặc là production repository nếu cần thiết.
Chắc hẳn mọi người đọc example hay tutorial cũng đều thấy axios luôn được sử dụng trong component. Vậy có vấn đề gì xảy ra chỗ này:
Đương nhiên là thay đổi 1 file sẽ dễ dàng hơn là thay đổi 30 file rồi đúng không?
Trong case này, để đơn giản hoá code và có thể định nghĩa được 1 vài loại resource khác nhau thì mình sẽ sử dụng POJO (Plain Old JavaScript Objects). Đương nhiên có thể sử dụng Class nếu bạn muốn.
Bây giờ cùng bắt đầu đi định nghĩa asxios nhé.
Mình sẽ đặt tên file là Repository.js vì nó đảm nhiệm việc kết nối đến các resources.
Cũng có 1 vài người thích cái tên Service hay là API, nhưng trong hoàn cảnh này mình thấy cái tên Repository có vẻ hợp lí hơn.
Tiếp theo chúng ta sẽ đi định nghĩa cho từng Entity của project.
Ví dụ như bạn có 1 blog. Khi đó chúng ta sẽ có 1 Entity là posts. Và bây giờ chúng ta sẽ đi định nghĩa tất cả các thao tác CRUD (Create Update Delete).
Và khi đó postsRepository.js sẽ trở thành như sau:
Tiếp theo chúng ta sẽ đi tạo Factory.
Nhìn vào trên ta thấy việc tạo Repository từ Factory trở nên thật simple phải không?
Hơn nữa ở đây ta cũng dễ dàng tạo mock repository (phù hợp với từng môi trường ví dụ develop, staging, production) hay thêm 1 vài logic vào trong hàm get ở trên cũng đều được hết.
Còn đây là cách áp dụng vào trong component:
Nhìn vào chúng ta thấy nó simple phải không nào? Vì phần logic đã được tách ra ở 1 chỗ khác nên việc dùng 1 endpoint khác như GraphSQL cũng hoàn toàn có thể.
Hiện tại pattern này mình đang áp dụng vào dự án thấy khá ngon. Nhưng điều đó cũng không có nghĩa là nó phù hợp với dự án của các bạn.
Tuy nhiên, theo mình thấy thì pattern này có 1 số ưu điểm sau:
Quick Links
Social Media