2016-03-25 3 views
1

変数に格納されたJSONから、show: function(id)という名前のルータ関数から現在のIDの名前を取得できます。しかし、JSON変数を使用する代わりにURLからコレクションを取得すると、未定義のTypeErrorが返されます。私が見てきた何バックボーン:ルータのURLからのフェッチは未定義ですが、コレクションがJSONを変数から取得すると機能します

console.log(this.collection.get(id).get('name')); 

は、私はJSON変数を使用する場合show functionが正常に動作しますが、私はURLからフェッチするとき、fetchが成功した後show functionが実行されるということです。

私は間違っていますか?なぜURLからのフェッチが未定義になるのですか?どうすればそれを動作させることができますか?

次のコードは架空のもので、コードの関連部分のみを示しています。コードブロックの最後の2つのケースを参照してください。
jsFiddle here

// Data 1 with variable 
var heroes = [ 
    {"id": "1", "name": "Batman"}, 
    {"id": "2", "name": "Superman"}, 
]; 

// Data 2 from url: http://example.com/heroes.json 
[ 
    {"id": "1", "name": "Batman"}, 
    {"id": "2", "name": "Superman"}, 
]; 

HeroesCollection = Backbone.Collection.extend({ 
    model: HeroesModel, 
    url: 'http://example.com/heroes.json' 
}); 

HeroesRouter = Backbone.Router.extend({ 
    // I use two shows to graphic this example 
    routes: { 
    '': 'index', 
    ':id': 'show' 
    }, 

    initialize: function(options) { 
    this.collection = options.collection; 
    this.collection.fetch(); 
    // this.collection.fetch({async:false}); this fixes my problem, but I heard it is a bad practice 
    }, 

    index: function() { 

    }, 

    show: function(id) { 
    console.log(this.collection.get(id).get('name')); 
     // Case #1: When Collection loads from a Variable 
     // id 1 returns: 'Batman' 

     // Case #2: When Collection fetchs from URL, id 1 returns: 
     // TypeError: this.collection.get(...) is undefined 
    } 

}); 

// Case #1: collection loads JSON from a variable 
var heroesCollection = new HeroesCollection(heroes); 
// Case #2: collection loads JSON with fetch in router's initialize 
// var heroesCollection = new HeroesCollection(); 
var heroesRouter = new HeroesRouter({collection: heroesCollection}); 
+0

アプリケーションはどのように ':id'と一致するルートにナビゲートしますか? –

+0

@TJナビゲートする一般的な方法は、各アイテムがそのIDにリンクするインデックスページからです。ナビゲートする別の方法は、正確なURLをIDで貼り付けることです。 –

+0

私は上記のコードをどのように/いつ行っているのか聞いています。フェッチが完了する前にアドレスバーに直接IDを入力すると、明らかに機能しなくなり、そのようなことを処理する必要があります。それはあなたがやっていることですか?フェッチされたデータを表示するビューはどこに作成されていますか? –

答えて

1

どのように?それはしばらくしていますが、これはあなたが達成しようとしているものに対するより良いアプローチのようです。基本的なコンセプトは、あなたがあなたのショールートに移動すると、ショーを実行するということです。このメソッドは、新しい空のコレクションを作成し、そのコレクションのデータを取得します。それと並行して、JSON(Herosのコレクションを作成する)でリクエストが終了したときに実行されるsuccessメソッド(Françoisが示すように)を渡します。

リモートデータの問題に遭遇した理由は、要求のデータが入力される前にthis.collectionにアクセスしようとしていたためです。

要求が非同期であることを覚えておく必要があります。これは、要求の処理中にコードの実行が継続することを意味します。

HeroesCollection = Backbone.Collection.extend({ 
    model: HeroesModel, 
    url: 'http://example.com/heroes.json' 
}); 

HeroesRouter = Backbone.Router.extend({ 
    routes: { 
    '': 'index', 
    ':id': 'show' 
    }, 

    index: function() { 

    }, 

    show: function(id) { 
    this.herosCollection = new HerosCollection(); 
    this.herosCollection.fetch({ 
     success: function(collection, response, options) { 
     console.log(this.get(id).get('name')); 
     } 
    }); 
    } 

}); 
+0

あなたのソリューションはうまく動作します。各ルートアクションでデータを取得するのがよい方法だと思いますか?私はインデックスアクションのためのデータを取得する必要があると考えています。 –

+0

どうしてですか?フェッチする!wan'tなら、APIでモデルをラップして、ラウンドトリップを心配している場合にキャッシュをローカルキャッシュすることができます。しかし、これは必要ではないと私は考えています。 –

+0

これは通常、ルータ。しかし、私はそれが悪い習慣であるとは言いません。それはあなたのコードを整理する方法によって異なります。私は個人的にビューをモデルにバインドするのが好きです。 –

1

あなたは、コレクションをロードするために終了したルータのショー '関数をトリガする必要があります。 this.collection.fetch({async:false}); javascriptコード全体が待機しているため(async:false)、さらに進む前にajax呼び出しを終了するため、問題を修正します。

他の最適な解決策は、結果を使用する前にコレクションがフェッチされるのを待つことです。

基本的にはこの程度

MyCollection.fetch({ 
    success: function(model, reponse) { 
     // do wtv you want with the result here or trigger router show method... 
    } 
}); 
関連する問題