我正在尝试做一些可能无法完成的事情,但实际上我正在尝试收集数据然后将其全部传递给视图,但我认为承诺的方式是不可能的。
所以我拥有的是:
create: function() {
$('#blog-manage').empty();
var options = {reset: true};
var getTags = new AisisWriter.Collections.Tags({per: 9999});
getTags.fetch(options).then(function(data){
this.tags = data.tags //=> this.tags is a class level variable. data.tags = array of 5 objects.
}, this);
console.log(this.tags) //=> null
var createPost = new AisisWriter.Views.CreatePost({tags: this.tags });
createPost.render();
},
我无法弄清楚为什么在promise中可以将data.tags分配给this.tags但是this.tags
的一边是null。我已将this
绑定到回调函数。
答案 0 :(得分:3)
除非您在调用console.log(this.tags)时将AJAX选项更改为同步,否则可能尚未设置this.tags。您可以尝试将此日志语句和createPost移动到promise回调中,如下所示。
create: function() {
$('#blog-manage').empty();
var options = {reset: true};
var getTags = new AisisWriter.Collections.Tags({per: 9999});
getTags.fetch(options).then(function(data){
this.tags = data.tags;
// move this logic inside the promise callback or put in a function
// to call when callback has completed
console.log(this.tags) //=> null
var createPost = new AisisWriter.Views.CreatePost({tags: this.tags });
createPost.render();
}, this);
},
作为对我的第一个回复的编辑,我创建了一个jsfiddle,展示了如何在不将承诺链接在一起并变得“混乱”的情况下处理这个问题。这可以在视图级别本身处理。您允许视图处理如何处理promise。这允许您分离视图逻辑并允许它处理其模型/集合更改时要执行的操作,即重新呈现自身。以下是jsfiddle中的一些JavaScript,请查看完整的JavaScript和HTML。
AisisWriter.Views.CreatePost = Backbone.View.extend({
template: _.template($("#tags-template").html()),
el: "#blog-manage",
initialize: function () {
// anytime our collection changes re-render view
// you can also use promise callback to call render
// OPTION 1
this.listenTo(this.collection, "add", this.render);
this.listenTo(this.collection, "remove", this.render);
// make the AJAX call to fetch items in our collection
// since backbone loads the collection for us we don't
// need the promise to assign data
// but you could attach the promise here
// but is completely optional
this.collection.fetch(this.options.ajaxOptions)
.then(_.bind(this.onFetchComplete, this)); // promise is optional
// OPTION 2
// .then(_bind(this.render, this)); // alternative
},
render: function () {
// wrap with tags to match how was in stack overflow post
var data = {
tags: this.collection.toJSON()
};
this.$el.html(this.template(data));
return this;
},
onFetchComplete: function (data) {
// .. do something with data...
// this is not needed though since Backbone
// will have placed data in collection
// this is only here to show you can do something else
// with the callback if you so desire
console.log('fetch of async data complete');
// sample data just for demo
// Backbone will have already populated the object
// you will notice b/c we used /echo/json as URL
// of collection it added an empty object
// since that is what jsfiddle sent back
this.collection.add([{
title: 'foo',
text: 'text of the post goes here'
}, {
title: 'bar',
text: 'text of this post goes here'
}]);
// alternatively you could call render manually
// instead of using listenTo in initialize method
// OPTION 3
// this.render();
}
});
答案 1 :(得分:3)
这里发生了几件事:
getTags.fetch(options).then(function(data){
this.tags = data.tags //=> this.tags is a class level variable. data.tags = array of 5 objects.
}, this);
由于JavaScript是异步的,因此在返回请求之前,将执行此操作之前或之后的任何操作。返回请求后,将履行承诺,但console.log
已经发生。
你的承诺回调中还有一个上下文切换 - 这意味着this
不再引用你的想法。虽然你说它已经绑定了,但你的功能是匿名的,所以它不是。我猜测的是你希望this
引用outter类。所以要修复它,使代码类似于:
var _this = this; // maintain a reference to your class instance
getTags.fetch(options).then(function(data){
_this.tags = data.tags;
console.log(_this.tags)
// do your rendering
}, this);