2015-12-20 29 views
6

Tôi muốn tạo một đối tượng trong Javascript.Truy cập 'this' của một đối tượng bên trong lời gọi lại lời hứa (sau đó)

Một trong các phương pháp nên thực hiện chuỗi lời hứa. Mỗi phương thức trong chuỗi phải truy cập một biến cấu hình là thành viên của đối tượng. Vấn đề là, các nhà điều hành this được thay đổi trong PromiseMethod2 và tôi không thể truy cập vào biến cấu hình (Nó hoạt động chính xác trong PromiseMethod1).

Dưới đây là mã của tôi:

var SomeObject(config) { 
    var that = this; 
    that.config = config; 
} 

SomeObject.prototype.SomeMethod = function() { 
    var that = this; 

    that.PromiseMethod1() 
     .then(that.PromiseMethod2) 
     .catch(console.error); 
    } 

SomeObject.prototype.PromiseMethod1 = function() { 
    var that = this; 
    config = that.config; 

    return SomePromise(); 
} 

SomeObject.prototype.PromiseMethod2 = function(someParams) { 
    var that = this; 
    config = that.config; 
    params = someParams; 

    return SomePromise(); 
} 


var someObject = new SomeObject(someConfig); 
someObject.SomeMethod().then(function() { 
    console.log('Done!'); 
} 

Tôi muốn sử dụng các đại biểu phương pháp trong chuỗi thay vì chỉ thực hiện:

that.PromiseMethod1().then(function(response) { return that.PromiseMethod2(that, response); }; 

Tôi không thể sử dụng phương pháp bind vì nó trông giống như nó được rebinded khi gọi lại được thực hiện.

Có giải pháp cho điều này không? Tại sao có sự khác biệt giữa PromiseMethod1PromiseMethod2?

+0

Làm thế nào để bạn giải quyết 'SomePromise'? – Kiril

+0

Mỗi phương pháp có thể làm việc khác nhau. Chủ yếu là tôi sử dụng 'Promise mới (giải quyết, từ chối)' và sau đó giải quyết (somePrams). Hoặc tôi sử dụng lời hứa của bên thứ ba như ElasticSearch hoặc Yêu cầu-Promise – shudima

+0

Bạn khẳng định rằng bạn không thể sử dụng liên kết, nhưng bạn đã thử chưa? Có vẻ như đó là giải pháp đúng. –

Trả lời

1

My thực khuyến cáo là không để sử dụng this hoặc new ở tất cả (và bạn có thể sử dụng Object.create nếu bạn vẫn muốn thừa kế):

var SomeObject = function(config) { 
    return { 
     PromiseMethod1: function(){ 
      return somePromise(config.foo); 
     }, 
     PromiseMethod2: function(x){ 
      return someOtherPromise(config.bar, x); 
     } 
    } 
} 

var instance = SomeObject({config: true}); 
instance.PromiseMethod1().then(instance.PromiseMethod2); 

Ở đây tôi đang sử dụng các bao đóng và khả năng của chúng để đưa các biến của phạm vi từ vựng cha mẹ vào lợi thế của tôi. Thay vì dựa vào JavaScript để đưa một hàm this vào chức năng của tôi vào thời gian chạy dựa trên đối tượng mà hàm được gọi, bởi vì như đã được chứng minh bởi vấn đề của bạn, điều đó không phải lúc nào cũng hoạt động.

Tuy nhiên, tôi biết rằng một cách độc đáo của mình để làm việc, vì vậy nếu bạn muốn thay vì gắn bó với this, bạn sẽ cần phải sử dụng bind để nói với JavaScript mà huyền diệu this -giá trị chức năng thuộc về:

var SomeObject function(config) { 
    this.config = config; 
} 

SomeObject.prototype.PromiseMethod1 = function(){ 
    return somePromise(this.config.foo); 
} 

SomeObject.prototype.PromiseMethod1 = function(x){ 
    return someOtherPromise(this.config.bar, x); 
} 

var instance = new SomeObject({config: true}); 
instance.PromiseMethod1().then(instance.PromiseMethod2.bind(instance)); //<- :(

Trong ví dụ SomeMethod bạn không thực sự đang sử dụng bind. Bạn vẫn cần phải ràng buộc vì bạn đang chuyển hàm vào .then(f) và mã nhận hàm không biết nữa đối tượng nào nên sử dụng cho số this. Bây giờ hãy xem lại mã được đề xuất trước đó của tôi.Không có this ses trong đó, do đó, những chức năng này không phụ thuộc vào đối tượng mà chúng đang được gọi, bạn có thể chuyển chúng xung quanh thành các hàm bậc cao nhiều như bạn muốn mà không cần phải bind hoặc that = this . :)

0

Tôi sẽ nói điều đó là không thể. Bạn cố gắng kết hợp 2 phương pháp khác nhau: method chainingpromises chaining. Tôi khuyên bạn nên xem lại kiến ​​trúc của bạn.

Điều duy nhất có thể nhìn thấy (nhưng cá nhân tôi không thích nó) nếu bạn có toàn quyền kiểm soát tất cả lời hứa bạn muốn sử dụng là chuyển giá trị cấu hình thông qua toàn bộ chuỗi lời hứa.

SomeObject.prototype.init = function() { 
    var that = this; 

    return new Promise(function(resolve, reject) { 
     resolve(that.config) 
    }); 
} 
SomeObject.prototype.PromiseMethod1 = function(config, params) { 
    return SomePromise(config, params); 
} 

SomeObject.prototype.PromiseMethod2 = function(config, someParams) { 
    return SomePromise(config, someParams); 
} 

SomePromise = function(config, params) { 
    return new Promise(function(resolve, reject) { 
     //some code here 
     resolve(config, newParamsFromSomeCode) 
    }); 
} 

Sau đó, bạn sẽ có thể gọi:

that.init().then(that.PromiseMethod1).then(that.PromiseMethod2); 

Nhưng một lần nữa, nó không giống như một mã tốt ...

+0

Không có phương pháp chuỗi. tất cả các phương thức đều nằm trong SomeObject. Tôi đã thử aproach này, vấn đề là Promise reolve method không hỗ trợ nhiều hơn 1 đối số. – shudima

+0

Có, nhưng bạn muốn gọi các phương thức của cùng một đối tượng một. Nếu bạn thực sự cần mã async - tôi khuyên bạn nên đặt các hoạt động async của bạn vào các đối tượng/lớp/thành phần riêng biệt/bất cứ điều gì và sử dụng chuỗi lời hứa đơn giản. – Kiril

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