patternjavascriptMinor
Avoiding RequireJS circular dependencies
Viewed 0 times
requirejsavoidingcirculardependencies
Problem
My
I need
I never ported an app to RequireJS before, and I got stuck on circular dependency problem, and this answer isn't quite clear to me, so I'm not sure if I applied the solution correctly.
I'm using AMD sugar style throughout the app, so here's what I came up with:
app.js
Extending
All other modules in the app return value normally (i.e. I'm not using
Is this an OK strategy for a Require.js Backbone app?
Are there better solutions (that will also work with optimizer or Almond)?
An example of how I'm using
zine_item_view.js
app module bootstraps a Backbone.js application.I need
app to be available in every other view for easy access to router, triggering navigation, etc.I never ported an app to RequireJS before, and I got stuck on circular dependency problem, and this answer isn't quite clear to me, so I'm not sure if I applied the solution correctly.
I'm using AMD sugar style throughout the app, so here's what I came up with:
app.js
define(function (require, exports) {
'use strict';
var _ = require('underscore'),
Backbone = require('backbone'),
Router = require('Router'),
AppView = require('common/views/app_view'),
// ...
return _.extend(exports, {
start: function () {
this.router = new Router();
Backbone.history.start();
this.appView = new AppView();
this.appView.render();
},
// ...
});
});Extending
exports instead of directly returning an object allows me to do app = require('app') in any view of the app without worrying about circular dependencies.All other modules in the app return value normally (i.e. I'm not using
exports anywhere else).Is this an OK strategy for a Require.js Backbone app?
Are there better solutions (that will also work with optimizer or Almond)?
An example of how I'm using
app in a (rather deeply nested) view:zine_item_view.js
define(function (require) {
'use strict';
var View = require('common/views/view'),
Misc = require('common/helpers/misc'),
app = require('app');
var ZineItemView = View.extend({
template: 'templates/social/items/zine_item.html',
events: {
'click': 'showZine'
},
showZine: function (e) {
if (!Misc.shouldHandleClick(e)) {
return;
}
app.presenter.showZine({
zine: this.model,
route: app.router.routeToZineTrending(this.model.id)
});
}
});
return ZineItemView;
});Solution
There are few ways to solve your problem with Backbone.js + Require.js and executing functions or changing routes from view.
Here is approach I've used multiple times:
It preferentual, but seems to be a standart (it's easier to see dependencies):
- Using Backbone.Router
Here is approach I've used multiple times:
'use strict';
// Your view --------------
define([
'jquery'
'backbone'
'common/views/view',
'common/helpers/misc'
], function ($, Backbone, View, Misc) {
var ZineItemView = View.extend({
...
showZine: function (e) {
if (!Misc.shouldHandleClick(e)) {
return;
}
// Pass all control from view to the router,
// see http://stackoverflow.com/a/20311253/1363799
Backbone.history.navigate('yourUrl_to_zine');
}
});
return ZineItemView;
});
// Main block --------------
require([
'jquery'
'backbone',
'app',
'ZineItemView'
], function($, Backbone, App, ZineItemView) {
...
var app = new App();
var zineItemView = new ZineItemView({...});
// Router way
var router = Backbone.Router.extend({
routes: {
"yourUrl_to_zine": "showZine"
},
showZine: function() {
// Here you gave access to zineItemView.model and zineItemView.model.id
app.presenter.showZine({
zine: zineItemView.model,
// I think next row becames obsolete
route: app.router.routeToZineTrending(zineItemView.model.id)
});
}
});
});
- Event-driven approach
'use strict';
// Your view --------------
define([
'jquery',
'backbone',
'common/views/view',
'common/helpers/misc'
], function ($, Backbone, View, Misc) {
var ZineItemView = View.extend({
...
showZine: function (e) {
if (!Misc.shouldHandleClick(e)) {
return;
}
var view = this;
// Trigger global event with desired parameters
$(window).trigger('showZine.App', {
zine: view.model,
modelId: view.model.id // probably it's obsolete, because you can get it from zine property
});
}
});
return ZineItemView;
});
// Somewhere in app block --------------
// lodash is a dependency, because we use bind method
var App = {
initialize: function() {
$(window).on('showZine.App', _.bind(this.presenter.showZine, this) );
},
presenter: {
showZine: function(event, paramsObj) {
// Here you have paramsObj,
// with paramsObj.zine = zineItemView.model
// and paramsObj.modelId = zineItemView.model.id
// Call app.router.routeToZineTrending from here, but be aware about value of `this` and `app` variables
}
}
};- Syntax of module defining (optional)
It preferentual, but seems to be a standart (it's easier to see dependencies):
'use strict';
define([
'common/views/view',
'common/helpers/misc',
'app'
], function (View, Misc, app) {
var ZineItemView = View.extend({
...
});
return ZineItemView;
});Code Snippets
'use strict';
// Your view --------------
define([
'jquery',
'backbone',
'common/views/view',
'common/helpers/misc'
], function ($, Backbone, View, Misc) {
var ZineItemView = View.extend({
...
showZine: function (e) {
if (!Misc.shouldHandleClick(e)) {
return;
}
var view = this;
// Trigger global event with desired parameters
$(window).trigger('showZine.App', {
zine: view.model,
modelId: view.model.id // probably it's obsolete, because you can get it from zine property
});
}
});
return ZineItemView;
});
// Somewhere in app block --------------
// lodash is a dependency, because we use bind method
var App = {
initialize: function() {
$(window).on('showZine.App', _.bind(this.presenter.showZine, this) );
},
presenter: {
showZine: function(event, paramsObj) {
// Here you have paramsObj,
// with paramsObj.zine = zineItemView.model
// and paramsObj.modelId = zineItemView.model.id
// Call app.router.routeToZineTrending from here, but be aware about value of `this` and `app` variables
}
}
};'use strict';
define([
'common/views/view',
'common/helpers/misc',
'app'
], function (View, Misc, app) {
var ZineItemView = View.extend({
...
});
return ZineItemView;
});Context
StackExchange Code Review Q#40160, answer score: 5
Revisions (0)
No revisions yet.