Thứ Bảy, 29 tháng 11, 2014

Tạo todo app đơn giản sử dụng backbonejs và requirejs

Tạo TODO app với Backbonejs và Requirejs.


Theo như bài trước chúng ta đã có thể tạo được một app cực kì đơn giản với backbonejs. Nhìn lại thì code đó vẫn còn lung tung lắm, khó quản lý code :).


Chính vì vậy hôm nay mình sẽ giới thiệu sử dụng thằng backbonejs này underscorejs, requirejs để refractor lại TODO app đó.


Đầu tiên mình cũng cần một chút khái niệm về requirejs đã nhé.
Requirejs là một thư viện hỗ trợ script loading, nhằm cải thiện tốc độ load js file, hỗ trợ load theo các module.


Với hướng dẫn lần trước mình sẽ include script file theo thứ tự:
<script type="text/javascript" src="lib/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="lib/underscore.js"></script>
<script type="text/javascript" src="lib/backbone.js"></script>
<script type="text/javascript" src="todo/app.js"></script><!-- Main app file -->


Nếu load theo cách trên thì trình duyệt sẽ phải load script file một cách tuần tự, từ trên xuống. Điều đó sẽ ảnh hưởng 1 chút đến tốc độ render của website chúng ta.


Một cách khác nếu sử dụng requirejs, thì các script file sẽ được load sau khi document đã được load xong, và các script file của chúng ta sẽ load theo cơ chế bất đồng bộ nhưng vẫn đảm bảo các file được load theo đúng thứ tự.


<script data-main="js/main.js" src="js/require.js"></script><!-- Main app file -->


Nội dung main.js


Screen Shot 2014-11-28 at 10.18.50 PM.png


Cách các script file được load trên trình duyệt.


Screen Shot 2014-11-28 at 10.22.01 PM.png

Ok mình sẽ quay lại TODO app của chúng ta

Todo.png

Mình sẽ liệt kê lại các thành phần chính trong TODO app lần trước.
  • TodoModel
  • TodoView
  • TodoListView
  • TodoCollection
  • AppView
Lần này cấu trúc app mình có thay đổi một chút như sau:

Screen Shot 2014-11-29 at 7.06.34 AM.png


Đi thẳng vào code luôn nhé. :)

// khai báo TodoModel (model/todo.js)
Screen Shot 2014-11-29 at 7.16.40 AM.png

// khai báo TodoCollection (collection/todo.js)
Screen Shot 2014-11-29 at 11.34.01 PM.png

// khai báo TodoView (view/todo.js)
Screen Shot 2014-11-29 at 11.35.31 PM.png

// khai báo TodoListView (view/todo-list.js)
Screen Shot 2014-11-29 at 11.39.14 PM.png

// khai báo AppView (app.js)
Screen Shot 2014-11-29 at 11.41.10 PM.png

// Khai báo main app (main.js)
Screen Shot 2014-11-29 at 11.42.26 PM.png


Nếu các bạn để ý có thể thấy rằng đối với mỗi đối tượng như TodoModel, TodoView, … mình đều khai báo cũng không khác hướng dẫn lần trước cho lắm, chỉ có 1 điểm khác biệt là lần này mình khai báo như một module riêng biệt và sẽ được gọi thông qua requirejs.


Kiểu khai báo 1 module của requirejs như sau:
define([?dependency], function(dep1, dep2, ….){
// Some function with dep1
// Some function with dep2
// ….
});


hoặc
define(function(require){
var something = require(some_path);
});

Link Demo: http://vntrace.github.io/backbone/bb-rj/

Xin lỗi các bạn do mình không có nhiều thời gian, nên chỉ có thể đăng được nội dung hd như trên, chưa có đi vào giải thích từng vấn đề cụ thể được. Nếu các bạn quan tâm hơn có thể để lại comment bên dưới, đảm bảo mình sẽ reply lại nhiệt tình nhé.

Thứ Năm, 29 tháng 5, 2014

Lập trình bất đồng bộ

Exceptions và try/catch (phương án dự phòng)

Nói đến exception và try/catch thì mình nghĩ rằng không coder nào không biết hoặc chưa từng nghe nói tới. Khi lập trình nhiều khi có những điều xảy ra ngoài ý muốn và mình muốn điều đó không ảnh hưởng gì đến ứng dụng mình đang chạy thì mình sử dụng try/catch, có thể giúp mình nhận biết được tình huống không mong muốn đó (hay còn gọi là exception – ngoại lệ), và sau đó đưa ra một phương án dự phòng (catch).
Thật ra trước giờ mình chỉ làm việc trên 2 ngôn ngữ chính đó là PHP và Javascipt thôi, nên có thể một số gì mình viết chỉ liên quan tới 2 thằng này nên các bạn thông cảm và góp ý luôn nhé !

Function getResult() {
                Try {
                                result = thisMightFail();
                } catch (e) {
                                result = recoverFromFailure(e);
                }
}

Đơn giản là hàm thisMightFail() sẽ trả về ngoại lệ (Error) nào đó và sẽ được bắt lại và một phương án dự phòng được thực hiện recoverFromFailure(e);  Tất cả đều chạy bình thường bởi vì hàm thisMightFail() chạy đồng bộ (có nghĩa là sẽ trả về một giá trị mặc định nào đó chẳng hạn). Vậy chuyện gì sẽ xảy ra khi hàm thisMightFail() được định nghĩa lại:
Function thisMightFail() {
                xhrGet(‘/getResult’, callback, errback); // ajax request
}
thisMightFail() đã chuyển từ xử lý đồng bộ sang bất đồng bộ bằng việc thực hiện một ajax request để lấy dữ liệu về. Haha, tất cả mọi thứ bắt đầu thay đổi, làm sao đây ? J
Mình sẽ quay lại block try/catch lúc đầu, và dường như chúng không còn thích hợp cho thay đổi này rồi. Nhưng đây không phải là điểm kết, vẫn còn một chút hy vọng đấy chứ, đó là chúng ta phải hỗ trợ thêm function xử lý callback cho các trường hợp có hoặc không có dữ liệu trả về.
Function thisMightFail(callback, errorback) {
                xhrGet(‘/getResult’, callback, errorback);
}

Function getResult(callback) {
                thisMightFail(callback, function(e){
                                var result = recoverFromFailure(e)
                                callback(result);
                });
}
Tip:  Nếu xử lý try/catch lúc đầu có thêm finally:
Try {
                result = thisMightFail();
} catch (e) {
                result = recoverFromFailure(e);
} finally {
                // Do something at the end
}
Và giải pháp là chúng ta phải thêm một alwaysback callback function cho thisMightFail()
Function thisMightFail(callback, errorback, alwaysback) {
                xhrGet(‘/getResult’, callback, errorback, alwaysback);
}

Tóm lại:
Chúng ta sử dụng callback function cho lập trình bất đồng bộ khi:
·         Không còn có thể sử dụng các phương thức gọi và nhận đơn giản như trước
·         Không còn có thể xử lý lỗi trả về bằng try/catch/finally


Chủ Nhật, 20 tháng 4, 2014

Giới thiệu browserify và tổ chức module trong javascript



BrowserifyNew way to build your javascript snippet & api

Bạn đã từng quen thuộc với nodejs và thích cách gọi các module với hàm require(), nhưng anh ấy chỉ hỗ trợ viết app phía server thôi J. Với browserify bạn sẽ tiếp cận được với hàm require() phía client, nó cho phép bạn có thể sử dụng các module từ npm mà đã được compile cho browser. Hoặc có thể đơn giản trong việc tổ chức module cho app của mình (requirejs là một thằng thay thế).
Ví dụ đơn giản trước nhé, nói nhiều mất công nhanh chán J
Cấu trúc app đơn giản nhé:
/app
main.js
                helper.js

helper.js
module.exports = {
                timeToHumanDate: function(time) {
                                // Format timestamp to time which human can read
},
capitalize: function(str) {
               
}
}

Mình định nghĩa module helper theo style của nodejs, trả về một object với 2 function timeToHumanDate và capitalize như trên

main.js
var helper = require(‘helper’);

var time = Date.now(),
                humanDate = helper.timeToHumanDate(time);

document.write(time);

Thực hiện require module helper vừa mới định nghĩa ở trên var helper = require(‘helper’);
Trong file main.js mình sẽ sử dụng helper để format timestamp với hàm helper.timeToHumanDate() và in nó ra trình duyệt document.write(time);

Cực kì đơn giản ^^ và cuối cùng là build code: browserify main.js -o build.js chúng ta sẽ được file build.js, và chỉ đơn giản là sử dụng file này gắn vào trang html của bạn mà thôi.

Ví dụ là vậy thôi, cũng chỉ mới là giới thiệu và đọc xem như thế nào, để test thử ví dụ đó trước hết bạn cần cài đặt browserify trước đã: npm install -g browserify

Bạn có  thể tham khảo thêm tại đây: http://browserify.org/
Bài tiếp theo mình sẽ giới thiệu build một js api với template html + underscorejs