Below is the code which I saved as a file named listView.js. I wonder about how the inner variable working. For example, variable dtRngPckr is defined in the initialize within Backbone.View and whenever application move to the other part, I called onClose function to null the said variable. And when I need to reuse this module, there must be an error occur in render function. It triggered error not a function
define(function (require) {
"use strict";
var $ = require('jquery'),
_ = require('underscore'),
Backbone = require('backbone'),
dtRngPckr;
return Backbone.View.extend({
initialize: function (opt) {
dtRngPckr = require('daterangepicker');
},
render: function () {
dtRngPckr();
},
onClose: function () {
dtRngPckr = null;
}
});
});
Could someone tell me how's exactly this variable working
RequireJS caches the return value of a module so it only has to fetch it once, all prior variables are shared between the instances. To use a separate daterangepicker for each instance, you could attach it to your view:
return Backbone.View.extend({
initialize: function (opt) {
this.dtRngPckr = require('daterangepicker');
},
render: function () {
this.dtRngPckr();
},
onClose: function () {
this.dtRngPckr = null;
}
});
Related
I want to use Jasmine to spyOn a module which exports a method directly:
myModule
module.exports = (arg, arg) => {
//do something...
callAMethod();
//return
}
Jasmine
spyOn(myModule);
// since I don't have any method to use spyOn(myModule, <method>)
I found I could use this:
//describe..
var myModule = require('./myModule');
it...
myModule = jasmine.createSpy().and.callFake(function() {
return false;
}); // <-this should work
functionBeingTested(..args);
expect(myModule).toHaveBeenCalled(); /*I get false, even if
it is actually called
in the functionBeingTested*/
Another solution i found was to spyOn myModule.prototype or set jasmine.createSpy().and.returnValue(false) but I have no success with both either.
How can I use spyOn like I said above?
I've created a simple snippet which mimics the require js
functionality to load the library and call the method.
I've listed three spies each with a different scenario explaining how
to spy
Note:
I've not used the require.js in itself but mimicked its functionality
however
Because the require.js exports the module.exports, we have no
control over the functionality of the require call and hence we might
not be able to install a spy on that method.
Please follow the each it case to for the description.
Hope this helps!
var callAMethod = function() {
return "Hello";
}
var myModule = {};
myModule.exports = function(name, title) {
return callAMethod() + " " + title + "." + name;
}
// Note that this require mimics the actual require.js require methodology, bascially returns the instantiated version of the library to be used.
var require = function() {
return myModule.exports;
}
// some function that uses the require library to load the js and then does something with it.
var testFunc = function() {
var myMod = require('abc');
return myMod("Bruce", "Mr");
}
describe('test mymodule', function() {
// This test fails because though you are mocking the instance here and not the actual call.
it('test that fails', function() {
var myModuleTest = require('abc');
myModuleTest = jasmine.createSpy().and.callFake(function() {
return false;
});
var result = testFunc();
console.log(result);
expect(result).toBe(false);
});
// this test passes since we have hijacked the require attribute itself and then routed its call to return the Boolean true which means that myModule now return the true statement
it('test that passes', function() {
require = jasmine.createSpy().and.callFake(function() {
return function() {
return true;
};
});
var result = testFunc();
console.log(result);
expect(result).toBe(true);
});
//callAMethod method call from module.exports may not tested since its the require js that does this call and you have no hook into it, however you can directly test the method like this
it('test callAMethod', function() {
console.log(myModule.exports("Bruce", "Mr"));
spyOn(myModule, 'exports').and.returnValue("Hello Mr.Wayne!");
var testVal = myModule.exports("Bruce", "Mr");
expect(testVal).toEqual("Hello Mr.Wayne!");
})
});
This question already has answers here:
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
(4 answers)
Closed 6 years ago.
This code:
'use strict'
function Ob() {}
Ob.prototype.add = () => {
this.inc()
}
Ob.prototype.inc = () => {
console.log(' Inc called ');
}
module.exports = new Ob();
Is used by this code:
'use strict'
const ob = require('./ob')
ob.add();
When calling the ladder one, I get this error:
this.inc is not a function
When I change the first snippet to this:
'use strict'
function Ob() {}
Ob.prototype.add = function() {
this.inc();
}
Ob.prototype.inc = function() {
console.log(' Inc called ');
}
module.exports = new Ob();
Everything is fine and I get:
Inc called
Why does the first version throw?
Update: How would I make it work using arrow functions?
It doesn't work using arrow functions because they capture the this of the current scope. In your sample code
'use strict'
function Ob() {}
Ob.prototype.add = () => {
this.inc()
}
Ob.prototype.inc = () => {
console.log(' Inc called ');
}
module.exports = new Ob();
there is no this when this code runs (okay, there is one, but at least it's not the object instance that was created by the constructor). Essentially, this code is equivalent to:
'use strict'
const that = this;
function Ob() {}
Ob.prototype.add = function () {
that.inc()
}
Ob.prototype.inc = function () {
console.log(' Inc called ');
}
module.exports = new Ob();
and then it becomes apparent that actually there is no function for that.inc(). That's why it does not work.
How to fix this using arrow functions? Well, I'd say, don't use arrow functions here, because it makes absolutely no sense, and they are not just another way of writing "normal" functions, they are something slightly different.
How to fix this in general? Use the old-fashioned function keyword, and everything will work as expected :-)
Arrow functions don't introduce a new context. What that means is within an arrow function this will be the context from the function that it's contained within.
In the following example, the IIFE creates a context of window
(function () {
function Ob() {}
Ob.prototype.test = () => {
console.log(this === window);
};
o = new Ob();
o.test(); // true
}());
If you want to use a function with its own context, you'll have to use the full function keyword.
(function () {
function Ob() {}
Ob.prototype.test = function () {
console.log(this === window);
};
o = new Ob();
o.test(); // false
}());
I have service:
module.exports = {
functionA: function () {
sails.log('Hello!');
},
functionB: function () {
functionA();
}
}
then I got an error: "countPoint is not defined"
as title, I want to call another function on shared function, but I dont now how to do. Can anyone help me?
Sorry for my bad English~
FunctionA does not "exist" yet. Remember that it is a property from a JSON, not a function per se. Using quotes should help you understand:
module.exports = {
"functionA": function () {
sails.log('Hello!');
},
"functionB": function () {
functionA(); // this is actually module.exports.functionA()
}
}
Put your functions outside module.exports and reference them without ():
module.exports = {
"functionA": functionA,
"functionB": functionA
}
function functionA() {
sails.log('Hello!');
}
#nodeman: tks for your response. But I can not call function functionA() outside of module. Then I found a solution:
file Demo.js:
module.exports = {
functionA: function () {
sails.log('Hello!');
},
functionB: function () {
Demo.functionA();
}
}
by call function with file name prefix, I called function in same module.
I'd like to use momentjs (more generally, any other function) as helper in a Jade template, both for the server and the client. On the server (Express.js 3.x), I'm adding it to app.locals, and it works fine:
Server-side
// Locals
app.locals.moment = require('moment');
// Routes
app.get('/', function (req, res) {
res.render('index.jade')
});
app.listen(config.get('server').port);
So using the moment helper works fine when the template (index.jade) is rendered by the server and then served at / as plain HTML.
Client-side
On the client (RequireJS modules system) I'm using Backbone.js along with, again, Jade in order to render views. How can I use moment helper in navbar.jade?
define(
['jade', 'backbone', 'text!views/navbar.jade'],
function (Jade, Backbone, navbarTemplate) {
return Backbone.View.extend({
initialize: function () {
this.template = Jade.compile(navbarTemplate);
},
render: function () {
this.$el.html(this.template(this.model));
return this;
}
});
}
);
EDIT: based on Peter Lyons suggestion, I've wrapped compile function. moment works but foo doesn't (p= moment() vs p= foo(), the latter gives me cannot call function of undefined):
define(['jade', 'lodash', 'moment'], function (Jade, _) {
return {
compile: function(str, options) {
options.locals = _.extend({
moment: require('moment'),
foo: function () { return 'bar'; }
}, options.locals);
return Jade.compile(str, options);
}
};
});
When you invoke the compiled template function in the browser, there's no out of the box app.locals, so you would have to code it.
//customJade.js module
define(function (require, exports) {
var jade = require('jade');
var moment = require('moment');
exports.compile = function(jadeString) {
//build the normal jade template function
var jadeFn = jade.compile(jadeString);
//build a wrapper function with same API
var customFn = function(locals) {
//in the wrapper, add your shared locals as needed
locals.moment = locals.moment || moment;
locals.appName = "Super Happy Fun App!";
//return the result of the real jade template function,
//but with combined locals
return jadeFn(locals);
};
//return your wrapper function instead of the regular jade function
return customFn;
}
});
.
//your backbone view module
define(['customJade', 'jadeTemplateString'], function (customJade, jadeTemplateString) {
//blah blah your View subclass...
template: customJade.compile(jadeTemplateString),
//...
});
I have a flag , named 'flag', and when this flag get's a specific value , I want to invoke a specific function.
anyone knows how to do that?
var EventEmitter = require("events").EventEmitter;
var flags = Object.create(EventEmitter.prototype);
Object.defineProperty(flags, "someFlag", {
get: function () {
return this._someFlag;
},
set: function (v) {
this._someFlag = v;
this.emit("someFlag", v);
}
});
flags.on("someFlag", callback);