2012-07-11 27 views
9

Tôi đã viết một tập lệnh nút lấy một số dữ liệu bằng cách yêu cầu dữ liệu REST API (sử dụng yêu cầu thư viện). Nó bao gồm một vài chức năng như vậy:cách giải quyết vấn đề 'này' với các thư viện nút như không đồng bộ và yêu cầu

var data = { /* object to store all data */ }, 
function getKloutData() { 
    request(url, function() { /* store data */} 
} 
// and a function for twitter data 

Bởi vì tôi muốn làm một số nội dung sau khi lấy tất cả các tôi đã sử dụng async thư viện để chạy tất cả các lấy các chức năng như vậy:

async.parallel([ getTwitterData, getKloutData ], function() { 
    console.log('done'); 
}); 

này tất cả đều hoạt động tốt, tuy nhiên tôi muốn đặt mọi thứ bên trong một mẫu đối tượng để tôi có thể tìm nạp nhiều tài khoản cùng một lúc:

function Fetcher(name) { 
    this.userID = '' 
    this.user = { /* data */ } 
    this.init(); 
} 
Fetcher.prototype.init = function() { 
    async.parallel([ this.getTwitterData, this.getKloutData ], function() { 
     console.log('done'); 
    }); 
} 
Fetcher.prototype.getKloutData = function(callback) { 
    request(url, function() { /* store data */ }); 
}; 

Điều này không hoạt động vì không đồng bộ và yêu cầu thay đổi điều này bối cảnh. Cách duy nhất tôi có thể giải quyết vấn đề này là ràng buộc mọi thứ tôi chuyển qua async và yêu cầu:

Fetcher.prototype.init = function() { 
    async.parallel([ this.getTwitterData.bind(this), this.getKloutData.bind(this) ], function() { 
     console.log('done'); 
    }); 
} 
Fetcher.prototype.getKloutData = function(callback) { 
    function saveData() { 
     /* store data */ 
    } 


    request(url, saveData.bind(this); 
}; 

Tôi đang làm gì đó sai cơ bản hay gì đó? Tôi nghĩ rằng quay trở lại kịch bản và forking nó để child_processes tạo ra nhiều chi phí.

Trả lời

9

Bạn đang thực hiện chính xác.

Cách khác là để giữ một tham chiếu đến đối tượng luôn trong bối cảnh thay vì sử dụng bind, nhưng điều đó đòi hỏi một số thể dục dụng cụ:

Fetcher.prototype.init = function() { 
    var self = this; 
    async.parallel([ 
     function(){ return self.getTwitterData() }, 
     function(){ return self.getKloutData() } 
    ], function() { 
     console.log('done'); 
    }); 
} 

Fetcher.prototype.getKloutData = function(callback) { 
    var self = this; 

    function saveData() { 
     // store data 
     self.blah(); 
    } 

    request(url, saveData); 
}; 

Bạn cũng có thể làm các ràng buộc trước:

Fetcher.prototype.bindAll = function(){ 
    this.getKloutData = this.prototype.getKloutData.bind(this); 
    this.getTwitterData = this.prototype.getTwitterData.bind(this); 
}; 

Fetcher.prototype.init = function(){ 
    this.bindAll(); 
    async.parallel([ this.getTwitterData, this.getKloutData ], function() { 
     console.log('done'); 
    }); 
}; 
+3

Thư viện gạch có một chức năng tiện dụng được gọi là 'bindAll' mà làm này ít đau đớn. Và nếu bạn chọn CoffeeScript, bạn chỉ có thể xác định các phương pháp với mũi tên chất béo và bạn sẽ không phải thực hiện bất kỳ ràng buộc rõ ràng nào cả. –

3

Bạn có thể tiết kiệm này vào một biến khác:

var me = this; 

Sau đó methis của bạn.

0

Phản đối đối tượng với chức năng này:

function newClass(klass) { 
    var obj = new klass; 

    $.map(obj, function(value, key) { 
     if (typeof value == "function") { 
      obj[key] = value.bind(obj); 
     } 
    }); 

    return obj; 
} 

Điều này sẽ làm au tomatic ràng buộc của tất cả các chức năng, vì vậy bạn sẽ nhận được đối tượng trong thói quen OOP phong cách, khi phương pháp bên trong các đối tượng có bối cảnh của đối tượng của nó.

Vì vậy, bạn nhanh chóng bạn không đối tượng thông qua việc:

var obj = new Fetcher(); 

Nhưng:

var obj = newClass(Fetcher); 
+0

câu hỏi ban đầu của tôi là trong môi trường nodejs nơi jQuery không có ý nghĩa. Ngoài ra các phương thức 'bindAll' trong gạch dưới và lodash (libs làm việc trong tất cả các môi trường JS) được thiết kế để làm điều này cho bạn. – askmike

Các vấn đề liên quan