2015-12-24 28 views
5

Prototipler içinde doğru this kapsamı ile çalışmak için söz veriyorum zor bir zaman geçiriyorum. Ben testler herZincirleme vaatler ve prototip `this`

'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; 
}); 

Ben

olsun
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); 
    }); 
}); 

});: Burada

benim kodudur Katı modda

şimdi bu $q
TypeError: 'undefined' is not an object (evaluating 'this.allItems') 

Ben undefined için then içine this ayarlar:

aşağıdaki hatayı alıyorum. Birden fazla yerde bind(this) kullanmayı denedim ama şans değil ... Herhangi bir fikir?

cevap

3

Bu gibi bir soruyu zaten yanıtladı here. Hala sorularınız varsa yorumlarda bana bildirin.

Upd. deneyin bu gibi resource.Scroll.prototype.nextPage yöntemini güncellemek için:

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 

Ama akılda tutulması - Bir geri arama işlevi geçerken bir then veya o olacak forEach vb içinthis bağlamı'un kaybolması. Bu nedenle, bind tam olarak, bir geri arama olarak this sözdizimini kullanan işlevi kullandığınızda kullanın.

+0

Yinelenen bir soru bulduğunuzu düşünüyorsanız, başka bir yanıtın bir kopyası/bağlantısı olan bir yanıtı göndermek yerine lütfen onu işaretleyin. – ChrisF