2015-12-24 11 views
5

私はプロトタイプの中で正しいthisスコープで作業することを約束するのは難しいです。ここで約束とプロトタイプ `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; 
}); 

私は

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

}を取得するテストを実行するたびに)。

私は次のエラーを取得する:

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

私は今、strictモードで$qundefinedthenthisを設定していること。私は複数の場所でbind(this)を使用してみましたが運がない...どんなアイデアですか?

答えて

3

私は既にhereのような質問に回答しています。 まだ質問がある場合は、コメントでお知らせください。

Upd。は、このようなあなたのresource.Scroll.prototype.nextPage方法を更新してください:

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 

しかし、心に留めておく - あなたはthenへのコールバックとして関数を渡すとき、またはforEachになどそれは'LL this文脈を失う。したがって、this構文をコールバックとして使用する関数を渡すときに、正確にbindを使用してください。

+0

重複した質問が見つかったと思われる場合は、別の回答へのコピー/リンクである回答を投稿するのではなく、それにフラグを立ててください。 – ChrisF