olya
olya

Reputation: 43

Backbone.js Problems with fetch() in IE

I'm building a web app with Django on back-end and Backbone.js on front-end

I have problems with IE when I'm trying to fetch data from the server. When I run my HTML page in IE, the collection fetch always invoke the error func.

My code:

$(function(){

var Chapter = Backbone.Model.extend({});

var Chapters = Backbone.Collection.extend({
    model: Chapter,
    url: 'http://ip.olya.ivanovss.info/chapters'
});

var chapters = new Chapters();

var Router = new (Backbone.Router.extend({
    routes: {
        "": "choose_activity",
        "/": "choose_activity"
    },

    choose_activity: function () {
        chapters.fetch({
            success: function () {
                AppView.render();
            },
            error: function() {
                alert('error');
            }
        });
    }
}))();

var AppView = new (Backbone.View.extend({
    el: '.popup',
    templates: {
        choose_activity: Handlebars.compile($('#tpl-activities').html())
    },
    render: function () {
        this.$el.html(this.templates["choose_activity"]({ chapters: chapters.toJSON()}));
    }
}))();

Backbone.history.start();
});

Django's View:

def chapters(request):
    chapters = list(Chapter.objects.order_by('id'))
    response = HttpResponse(json.dumps(chapters, default=encode_myway), mimetype='text/plain')
    if request.META.get('HTTP_ORIGIN', None) in ('http://localhost', 'http://html.olya.ivanovss.info', 'http://10.0.2.2'):
        response['Access-Control-Allow-Origin'] = request.META['HTTP_ORIGIN']
    return response

Thank you in advance

Upvotes: 2

Views: 1156

Answers (1)

Toli
Toli

Reputation: 5777

IE7 doesn't support CORS.

There are 2 ways around this. The EASY way is Proxy over your API. My Python is rusty (I'm a Node/PHP dev), but I'm sure that there are a million and one resources on how do do this. The good thing about this is you don't have to touch the API. But it means your local server has to CURL and return every single request from your API server.

And second (and much less server intensive way) is JSONP! The idea of JSONP is that it appends a <script> to the document with the URL you specify. jQuery appends a ?callback=jQueryNNN where NNN is a random number. So effectively when the <script> loads, it calls jQueryNNN('The Response Text') and jQuery knows to parse the response from there. The bad thing about this is you have to wrap all of your responses on the API side (which is super easy if you're just starting, not so easy if you already have an infrastructure built out).

The annoying things about JSONP is that by it's nature you can't do a POST/PUT/DELETE. BUT you can emulate it if you have access to the API:

Backbone.emulateHTTP = true;

model.save();  // POST to "/collection/id", with "_method=PUT" + header.

To integrate JSONP with Backbone is pretty simple (little secret Backbone.sync uses jQuery's $.ajax() and the options parameters forwards over to jQuery ;)).

For each one of your models/collections which access a cross origin you can add a su

var jsonpSync = function (method, model, options) {
    options.timeout = 10000; // for 404 responses
    options.dataType = "jsonp";
    return Backbone.sync(method, model, options);
};

In each collection and model what does cross-origin:

var MyCollection = Backbone.Collection.extend({
    sync  : jsonpSync
});

Or just overwrite the whole Backbone sync

Backbone.__sync = Backbone.sync;

var jsonpSync = function (method, model, options) {
    options.timeout = 10000; // for 404 responses
    options.dataType = "jsonp";
    return Backbone.__sync(method, model, options);
};

Backbone.sync = jsonpSync;

On the server side you can do: this to return a JSONP response (copy pasted here):

def randomTest(request):
    callback = request.GET.get('callback', '')
    req = {}
    req ['title'] = 'This is a constant result.'
    response = json.dumps(req)
    response = callback + '(' + response + ');'
    return HttpResponse(response, mimetype="application/json")

Upvotes: 1

Related Questions