2016-04-07 16 views
5

Thông thường nếu bạn không sử dụng những lời hứa, bạn có thể dễ dàng làmRàng buộc 'this` phạm vi của một hàm callback lời hứa

var a = function(cb){ 
    setTimeout(function(){ 
    var boundCb = cb.bind({hello: 'world'}); 
    boundCb(); 
    }, 100); 
}; 

a(function(){ 
    alert(this.hello); 
}); 

mà không phải là đặc biệt hữu ích nhất của thời đại (như bạn có thể vượt qua cùng những thứ như các đối số bình thường), nhưng nó cho phép một số mã cực kỳ dễ đọc và/hoặc đơn giản để sử dụng các giao diện.

Khi chuyển sang lời hứa tuy nhiên nó đột nhiên trở nên khó khăn hơn nhiều để thực hiện. Gì ngạc nhiên các sau không công việc (như resolve không phải là một tài liệu tham khảo trực tiếp)

var a = function(){ 
    return new Promise(function(resolve, reject){ 
    var boundResolve = resolve.bind({hello: 'word'}); 
    boundResolve(); 
    }); 
}; 

a().then(function(){ 
    alert(this.hello) 
}); 

như vậy là có cách nào ở tất cả để đạt được điều này?


postscriptum không cần thiết: 'May mắn' trong hoàn cảnh của tôi phạm vi this Tôi muốn thiết là đã giống như những gì phạm vi thisa(). Vì vậy, tôi hiện đang viết đơn giản .bind(this) sau mỗi chức năng gọi lại lời hứa duy nhất và trong tương lai tôi sẽ có thể sử dụng các chức năng mũi tên cho việc này, nhưng tôi đang tìm một giải pháp sạch hơn trong thời gian này.

+0

này không có vẻ như là một ý tưởng rất tốt với tôi. Bạn muốn kết hợp một lời hứa với một số giá trị 'này' khi bạn tạo ra nó, và sau đó ở một số nơi hoàn toàn riêng biệt tham chiếu đến giá trị đó với' this'? Có vẻ như một đầu trầy xước thực sự cho bất cứ ai duy trì mã của bạn vì nó phá vỡ [Nguyên tắc ít ngạc nhiên nhất] (https://en.wikipedia.org/wiki/Principle_of_least_astonishment). – JLRishe

+1

@ JLRishe: Từ một điểm tiêu thụ API, nó có thể có nhiều ý nghĩa, nhưng bạn sẽ phải xem xét bối cảnh rộng hơn của trường hợp cụ thể để hiểu. (Các nguyên tố polymer trong đó 'này' là thiết kế theo nghĩa vụ phải luôn đề cập đến phần tử hiện tại.) –

+0

Đủ công bằng. :) – JLRishe

Trả lời

4

Quảng cáo gốc không cung cấp chức năng này. Tuy nhiên, thư viện Bluebird Promise cung cấp Promise.prototype.bind

Dưới đây là một ví dụ sử dụng

MyClass.prototype.method = function() { 
    return fs.readFileAsync(this.file).bind(this) 
    .then(function(contents) { 
     var url = urlParse(contents); 
     return this.httpGetAsync(url); // this is bound to the MyClass instance 
    }).then(function(result) { 
     // this is still bound, further down the chain. 
     var refined = this.refine(result); 
     return this.writeRefinedAsync(refined); 
    }).catch(function(e) { 
     this.error(e.stack); // Even in event handlers 
    }); 
};
+0

Vâng, tôi lo sợ như vậy @ "Native Promises không cung cấp chức năng này." Không muốn vội vàng kết luận mặc dù trước khi kiểm tra lần đầu :). Thực sự sẽ không phiền nếu họ thêm vào API, sẽ hữu ích trong nhiều cách. –

+3

Gọi lại lời hứa được thiết kế với suy nghĩ không trạng thái. 'this' ngụ ý trạng thái, không phải là" đường sạch ". –

+0

Không cố gắng để cung cấp cho họ bất kỳ trạng thái nào (như tôi muốn 'ràng buộc' phạm vi 'này' rộng hơn 'trở lại'), nhưng hoàn toàn có được những gì bạn đang nói. –

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