Lập trình Promise với BlueBird quá các ví dụ - Phần 1

Trước khi vào phần 2, chúng ta thử làm thêm một ví dụ nữa khởi động. Hãy viết một đoạn code lấy địa chỉ IP máy tính đang chạy Node.js sau đó xác định vùng địa lý của địa chỉ IP này. Chức năng này có thể dùng để xác định thành phố - quốc gia của người tham gia diễn đàn hoặc chat. Để làm việc này chúng ta phải thực hiện 2 việc tuần tự:

  1. Lấy địa chỉ IP của máy hiện thời.
  2. Gửi IP đến trang dịch vụ http://www.geoplugin.com/ để khoanh vùng địa lý mà IP thuộc về
var promise = require("bluebird");
var needle = require('needle');
var getAsync = promise.promisify(needle.get);  //promisify riêng hàm get của module needle. Needle giống với request
console.time('taskA');
getAsync('http://ip.jsontest.com/').then(function(response){ 
        return response[1].ip;  //Trả địa chỉ IP
    }
).then(function(ip){  //Truyền địa chỉ IP để khoanh vùng địa lý
        return getAsync('http://www.geoplugin.net/json.gp?ip=' + ip);
    }
).then(function(response){
        console.log(response[1]); //In kết quả
        console.timeEnd('taskA'); //In tổng thời gian chạy 2 lệnh
    }
).catch(function (e) {  //Bắt lỗi nếu có
        console.error('Error:' + e);
    }
);

Kết quả trả về sẽ như sau

{
  "geoplugin_request":"113.190.11.211",
  "geoplugin_status":200,
  "geoplugin_credit":"Some of the returned data includes GeoLite data created by MaxMind, available from <a href=\\'http:\/\/www.maxmind.com\\'>http:\/\/www.maxmind.com<\/a>.",
  "geoplugin_city":"Hanoi",
  "geoplugin_region":"Ha Nội",
  "geoplugin_areaCode":"0",
  "geoplugin_dmaCode":"0",
  "geoplugin_countryCode":"VN",
  "geoplugin_countryName":"Vietnam",
  "geoplugin_continentCode":"AS",
  "geoplugin_latitude":"21.0333",
  "geoplugin_longitude":"105.849998",
  "geoplugin_regionCode":"44",
  "geoplugin_regionName":"Ha Noi",
  "geoplugin_currencyCode":"VND",
  "geoplugin_currencySymbol":"đ;",
  "geoplugin_currencySymbol_UTF8":"\u20ab",
  "geoplugin_currencyConverter":21349.2741
}
taskA: 1047ms

Một Promise có thể gắn nhiều hơn một hàm then

Nóng máy rồi thì thử một làm thêm tác vụ tiếp nhé. Sau khi lấy được kết quả JSON từ geo plugin trả về, thì vừa in ra và vừa ghi vào file trong cùng thư mục. Ở trong trường hợp này ta gắn hàm then để in ra màn hình console và hàm then để ghi vào file.

var promise = require("bluebird");
var needle = require('needle');
var fs = require('fs');
var getAsync = promise.promisify(needle.get);
var writeFileAsync = promise.promisify(fs.writeFile);

//Trả về promise ipDecodePromise
var ipDecodePromise = getAsync('http://ip.jsontest.com/').then(function(response){
        return response[1].ip;
    }
).then(function(ip){
        return getAsync('http://www.geoplugin.net/json.gp?ip=' + ip);
    }
);
//then thứ nhất
ipDecodePromise.then(function(response){
        console.log(response[1]);
    }
).catch(function (e) {
        console.error('Error:' + e);
    }
);
//then thứ hai
ipDecodePromise.then(function(response) {
    return writeFileAsync('ipdecode.txt', response[1]);
}).then(function(){
    console.log('Write to file ipdecode.txt successfully');
}).catch(function (e) {
        console.error('Error:' + e);
    }
);

Hàm getAsync thực ra trả về một Promise, một lời hứa sẽ thực hiện trong tương lai. Ở ví dụ một, ta nối luôn hàm then vào sau getAsync rồi. Còn ở ví dụ 2, ta cần trả về Promise để gắn sau nó nhiều hơn một hàm then.

Tổng kết

  1. Các hàm call back cổ điển sau khi promisify sẽ trả về một đối tượng Promise
  2. Có thể gắn then function vào luôn sau hàm đã được promisify, trong ví dụ này là getAsync
  3. Có thể gắn nhiều then function vào một đối tượng Promise

Chừa bài tiếp nhé. Mỗi bài viết một ít đọc đỡ mệt.