Backbone collection setting default API url using

2020-03-30 15:57发布

问题:

How can I set a default url/server for all my requests from collections and models in Backbone?

Example collection:

define([
    'backbone',
    '../models/communityModel'
], function(Backbone, CommunityModel){
    return Backbone.Collection.extend({
        url: '/communities', // localhost/communities should be api.local/communities
        model: CommunityModel,
        initialize: function () {
            // something
        }
    });
});

I make an initial AJAX call to get my settings including the url of the API (api.local).

How can I reroute the requests without passing it to all my models or hardcoding the url in the models and collections?

回答1:

your url takes a string or a function.

with your settings ajax call you can store it in a proper location, and go fetch that from the function

to use your example: suppose your ajax call, saved the url in a myApp.Settings.DefaultURL

define([
    'backbone',
    '../models/communityModel'
], function(Backbone, CommunityModel){
    return Backbone.Collection.extend({
        url: function(){
            return myApp.Settings.DefaultURL + '/communities';
        }, 
        model: CommunityModel,
        initialize: function () {
            // something
        }
    });
});

remark make sure this url is somehow caught or handled when it would be fired before your settings are set, if your initial ajax call fails or takes its time, your app might already be started without it's settings set, should one use a model.save() at that point, you would need to handle this.



回答2:

By over-riding (but not over-writing) the Backbone.sync method you can achieve the same result without having to add the same code to every single model/collection.

define(['underscore', 'backbone', 'myApp'], function (_, Backbone, myApp) {
    'use strict';

    // Store the original version of Backbone.sync
    var backboneSync = Backbone.sync;

    // Create a new version of Backbone.sync which calls the stored version after a few changes
    Backbone.sync = function (method, model, options) {
        /*
         * Change the `url` property of options to begin with the URL from settings
         * This works because the options object gets sent as the jQuery ajax options, which
         * includes the `url` property
         */
        options.url = myApp.Settings.DefaultURL + _.isFunction(model.url) ? model.url() : model.url;

        // Call the stored original Backbone.sync method with the new url property
        backboneSync(method, model, options);
    };
});

Then in your model/collection you can just declare the url as usual (e.g. url: '/events)

Don't forget to require the file with the new Backbone.sync code somewhere.