2015-12-24 11 views
5

Tôi đang gặp khó khăn để có được lời hứa để làm việc với phạm vi bên phải this bên trong các nguyên mẫu.Các lời hứa và nguyên mẫu đã được ghép đôi `this`

Đây là mã của tôi:

'use strict'; 

angular.module('testApp').factory('UrlSearchApi', 
    function($resource, URL_SEARCH_API, PAGE_SIZE, $q){ 

    var resource = $resource(URL_SEARCH_API); 

    resource.Scroll = function() { 
    return this.reset(); 
    }; 

    resource.Scroll.prototype.reset = function() { 
    this.visibleItems = []; 
    this.allItems = []; 
    this.busy = null; 
    return this; 
    }; 

    resource.Scroll.prototype.fetch = function(query){ 
    var params = {}; 
    if(query) { params.q = query; } 
    return resource.query(params).$promise; 
    }; 

    resource.Scroll.prototype.loadAllItems = function (results) { 
    var d = $q.defer(); 

    angular.forEach(results, function (result, i) { 
     this.allItems.push(result); 
     if(i === results.length - 1) { d.resolve(); } 
    }, this); 

    return d.promise; 
    }; 

    resource.Scroll.prototype.loadVisibleItems = function() { 
    var length = this.visibleItems.length, 
     offset = parseInt(length/PAGE_SIZE), 
     start = PAGE_SIZE * offset, 
     end = start + PAGE_SIZE, 
     subset = this.allItems.slice(start, end), 
     d = $q.defer(); 

    angular.forEach(subset, function (item, i) { 
     this.visibleItems.push(item); 
     if(i === subset.length - 1) { d.resolve(); } 
    }, this); 

    return d.promise; 
    }; 

    resource.Scroll.prototype.nextPage = function (query) { 
    if(this.busy) { return; } 

    console.log('nextPage ', query); 
    var tasks = [], 
     that = this; 

    if(!this.allItems.length) { 
     this.reset(); 
     this.busy = true; 
     return this.fetch(query) 
     .then(this.loadAllItems) 
     .then(this.loadVisibleItems) 
     .finally(function() { 
      this.busy = false; 
     }); 
    } else { 
     this.busy = true; 
     return this.loadVisibleItems().finally(function() { 
     this.busy = false; 
     }); 
    } 
    }; 

    return resource; 
}); 

Bất cứ khi nào tôi chạy các bài kiểm tra tôi nhận được

describe('#nextPage', function() { 
    var scroll; 

    describe('when there is NO search term (show all)', function() { 

    beforeEach(function (done) { 
     scroll = new UrlSearchApi.Scroll(); 

     $httpBackend.expectGET('/policy/search') 
     .respond(200, arrayGenerator(123)); 
     scroll.nextPage().then(done); 
     $httpBackend.flush(); 
     $rootScope.$apply(); 
    }); 

    it('should load all the items in all items variable', function() { 
     expect(scroll.allItems.length).toBe(123); 
    }); 
}); 

});

tôi nhận được lỗi sau:

TypeError: 'undefined' is not an object (evaluating 'this.allItems') 

bây giờ tôi $q rằng trong chế độ nghiêm ngặt đặt this bên then-undefined. Tôi đã thử sử dụng bind(this) ở nhiều nơi nhưng không may mắn ... Bất kỳ ý tưởng nào?

Trả lời

3

Tôi đã trả lời câu hỏi như thế này here. Chỉ cần cho tôi biết trong phần bình luận nếu bạn vẫn còn thắc mắc.

Cập nhật. Cố gắng cập nhật phương thức resource.Scroll.prototype.nextPage của bạn như thế này:

if(!this.allItems.length) { 
     this.reset(); 
     this.busy = true; 
     return this.fetch(query) 
     .then(this.loadAllItems.bind(this)) //bind here 
     .then(this.loadVisibleItems.bind(this)) // here 
     .finally(function() { 
      this.busy = false; 
     }.bind(this)); //and here 

Nhưng hãy nhớ - khi bạn vượt qua một chức năng như một callback đến một then hoặc forEach vv nó sẽ mất this ngữ cảnh. Vì vậy, hãy sử dụng chính xác bind khi bạn chuyển hàm sử dụng cú pháp this làm gọi lại.

+0

Nếu bạn cho rằng mình đã tìm thấy câu hỏi trùng lặp, hãy gắn cờ câu hỏi thay vì đăng câu trả lời là bản sao/liên kết đến câu trả lời khác. – ChrisF

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