2015-12-24 14 views
5

Mam trudności z otrzymaniem obietnic pracy z odpowiednim zakresem prototypów w zakresie this.Przykuty obietnice i prototyp "tego"

Oto mój kod:

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

Ilekroć uruchomić testy mam

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

});

pojawia się następujący błąd:

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

I teraz tego $q w trybie ścisłym ustawia this wewnątrz then do undefined. Próbowałem używać bind(this) w wielu miejscach, ale nie miałem szczęścia ... Jakieś pomysły?

Odpowiedz

3

Odpowiedziałem już na takie pytanie: here. Po prostu daj mi znać w komentarzach, jeśli nadal masz pytania.

Aktualizacja. Spróbuj zaktualizować swoją metodę resource.Scroll.prototype.nextPage tak:

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 

jednak pamiętać - kiedy przekazać funkcję jako zwrotnego Do then lub forEach itp Będzie stracić this kontekst. Tak więc, używaj bind dokładnie kiedy przełączysz funkcję, która używa składni this jako callback.

+0

Jeśli uważasz, że znalazłeś zduplikowane pytanie, zgłoś je, zamiast zamieszczać odpowiedź, która jest kopią/linkiem do innej odpowiedzi. – ChrisF