How to have multiple imports under a same variable - javascript

I want to organize my project imports with browserify so that I have a global utils variable from which I can call and execute functions much like jquery's $.
So in the end I want something like:
window.utils = ...
So I can use utils.aFunction();
I also want to divide my dependencies in several files, as an example, this would be my project:
libs
|_ math.js //Implements randomInt and RandomFloat methods
|_ connection.js //Implements isConnected method
utils.js //Calls all the required dependencies
My idea so far is to have something like this:
In libs/math.js:
module.exports = {
randInt: function() {
return 4;
},
randFloat: function() {
return 4.1;
}
};
And then I would do in utils.js:
var math = require('./libs/math');
var connection = require('./libs/connection');
var libs = [math, connection];
var utils = {};
for (var i = 0; i < libs.length; i++) {
for (var key in libs[i]) {
utils[key] = libs[i][key];
}
}
window.utils = utils;
This actually works just fine, but I don't know if it wasn't already solved by a library.
I have a feeling there are more efficient ways of doing this, what would be the recommended approach with browserify?

The code for throwing things into util object is definitely odd looking, and I wouldn't recommend this looping over all your required util submodules.
var libs = [math, connection];
var utils = {};
for (var i = 0; i < libs.length; i++) {
for (var key in libs[i]) {
utils[key] = libs[i][key];
}
}
If you were using a common js approach with webpack/browserify, you would simply declare your util to be global in the configuration file, and simply add the needed module.exports inside of your util.js
//connect.js
module.exports = {
isConnected: function(){
return true;
}
};
//math.js
module.exports = {
randInt: function() {
return 4;
},
randFloat: function() {
return 4.1;
}
};
//utils.js
exports.math = require('./math');
exports.connect = require('./connect');
//test.js
var utils = require('./utils');
console.log(utils.math.randInt());
console.log(utils.connect.isConnected());

Related

How to test my functions with gulp-jasmine, gulp-jasmine-browser or gulp-jasmine-phantom?

I've got gulp-jasmine-phantom running, but I get a ReferenceError: Tictactoe is not defined. I have the feeling I'm making some fundamental mistake.
My file-structure:
gulpfile.js
spec/test.js
source/js/tictactoe.js
A simplified version of the code:
gulp:
gulp.task('site:js:test', function() {
return gulp.src( 'spec/test.js')
.pipe(jasmine())});
test.js:
require("../source/js/tictactoe");
describe("Tictactoe", function() {
var t = new Tictactoe();
it("expects there to be able to add a mark", function() {
t.addMark([0,0], 1);
expect(t.board[0,0]).toBe(1);
});
});
tictactoe.js
function Tictactoe(size) {
this.size = size;
// default variables:
this.EMPTY = "";
this.board = [];
for ( var i = 0; i < this.size; i++ ) {
this.board[i] = [];
for ( var j = 0; j < this.size; j++) {
this.board[i][j] = this.EMPTY;
}
}
}
Tictactoe.prototype.addMark = function(position, player)
{}
I've also tried gulp.src( ['source/js/tictactoe.js', 'spec/test.js'] ) and then no require in the test.js. Also no success.
I've also tried gulp-jasmine and gulp-jasmine-browser. Can you help me make it work?
Thanks so much in advance!!
A related question to yours has been answered already over here: How to Load a File for Testing with Jasmine Node?
In short, you will need to create a module out of your tictactoe library, export the Tictactoe function, and then require it into a local variable that is accessible by Jasmine. The Tictactoe function is currently simply scoped into the local scope of the required JavaScript file.

Webpack - exporting module causes circular json reference

I am developing a simple javascript module for learning purposes. It looks like following:
function gen (props) {
var test = [];
for(var i = 0; i < 10; i++) {
test.push(props.start + i);
}
return test;
}
module.exports = function (props) {
return gen(props)
}
I am calling this module as:
<script>
import gen from './gen.js'
...
mounted: function () {
var x = gen({start: 5});
console.log(x);
}
...
</script>
But I am getting Converting circular structure to JSON error. What am I doing wrong?
EDIT: Forgot to mention, this is in VueJS. The whole module is a separate file and I am importing it into one of components.

calling function within module that is imported to another class

I am new to JavaScript (working my way through some basic tutorials). Can someone tell me what I am doing wrong here? I am trying to get the run function to reference the withinCircle function, then export the whole thing to another file so I can reference the run function. Feel free to modify my code anyway you want- I tried to follow "best" practices but I may have screwed up. Thanks!
var roleGuard = {
/** #param {Creep} creep **/
run: function(creep)
{
var target = creep.pos.findClosestByRange(FIND_HOSTILE_CREEPS, {filter: { owner: { username: 'Invader' } }});
if(target!=null)
{
console.log(new RoomPosition(target.pos.x,target.pos.y,'sim'));
//ranged attack here
//within 3, but further than 1
if(creep.pos.getRangeTo(target)<=3&&creep.pos.getRangeTo(target)>1)
{
creep.rangedAttack(target);
console.log("ranged attacking");
}
}
else
{
var pp=withinCircle(creep,target,3,'sim');
console.log(pp);
creep.moveTo(pp);
}
}
//------------------------------------------------------------
//move to closest point within z units of given evenmy
withinCircle: function(creep,target,z,room)
{
var targets = [new RoomPosition(target.pos.x-z,target.pos.y-z,room), new RoomPosition(target.pos.x+z,target.pos.y-z,room),new RoomPosition(target.pos.x-z,target.pos.y+z,room),new RoomPosition(target.pos.x+z,target.pos.y+z,room)];
var closest = creep.pos.findClosestByRange(targets);
return(closest);
}
//------------------------------------------------------------
};
module.exports = roleGuard;
Other file contains:
var roleGuard = require('role.guard');
for example:
// foo.js
function add(a,b){
return a + b
}
module.exports = add
and in the other file:
// bar.js
const add = require("./foo");
console.log(add(1,1))
those paths are relative to the file location. extension can be omitted.
you'll need node or browserify or webpack to make exports/require to work properly.
if you want a better explanation about modular javascript, look there, even if you not enter in the browserify world it will present you to what we can do nowadays.
EDIT:
in order to export more symbols you can do the following:
// foo2.js
function add(a,b){
return a + b
}
function multiply(a,b){
return a * b
}
module.exports = {
add:add,
multiply:multiply
}
And then in the consumer:
// bar2.js
const add = require("./foo2").add
const multiply = require("./foo2").multiply
//...
This is also valid:
// foo3.js
function add(a,b){
return a + b
}
exports.add = add
function multiply(a,b){
return a * b
}
exports.multiply = multiply
Consumer will need no relevant alteration:
// bar3.js
const add = require("./foo3").add
const multiply = require("./foo3").multiply
//...
If using babel/es6 modules have a different idion, which you can check there.

Mocha fails with variable not defined

I use mocha to test a function in a file. The testable function is implemented like this:
math.js
(function (exports) {
var MY_APP_ = MY_APP || {};
MY_APP_.utils = MY_APP_.utils || {};
MY_APP_.utils.math = MY_APP_.utils.math || {};
MY_APP_.utils.math.randomValue = function (min, max) {
return Math.floor(Math.random() * (max + 1 - min) + min);
};
exports.math = MY_APP_.utils.math;
})(this);
And here is the test:
math_test.js
var assert = require("assert");
var math = require("../../js/utils/math.js");
describe('Math', function() {
describe('randomValue', function () {
it('should return random values', function () {
// Fill array with random values between 0 and 10
var values = [];
for (var i = 0; i < 10000; i++) {
values.push(math.math.randomValue(0, 10));
}
// Count numbers
var result = {};
values.forEach(function(number) {
var numberAsString = number.toString();
result[numberAsString] = result[numberAsString] + 1 || 1;
});
// There must be at least two of each number
assert.equal(Object.keys(result).length, 11);
Object.keys(result).forEach(function(key) {
assert.equal(true, result[key] > 1);
});
});
});
});
The problem is that var MY_APP_ = MY_APP || {}; fails with an error message: MY_APP is not defined.
Sure, MY_APP is not defined in the scope of this test because it is defined in an another file called app.js. When I build the app, this app.js file is included before math.js and both of them are concatenated into a single production.js file. This works without problem.
The test works, however, if I replace the failing line with the following:
var MY_APP = {};
if (typeof(MY_APP) !== 'undefined') {
MY_APP_ = MY_APP;
} else {
MY_APP_ = {};
}
This looks stupid in my opinion. I would like to know the reason why mocha is failing since the code works perfectly well when I run it in a browser.
EDIT:
I think I have made a mistake. var MY_APP_ = MY_APP || {}; seems to never work if MY_APP is not defined so the only option is to declare MY_APP before using math.js
From what you showed I would think that you would receive an error, and that your direct test works.
In your test you initialize MY_APP to an empty object which allows it to run. But in your math.js file MY_APP is never initialized, so when you set var MY_APP = MY_APP it would never be able to set it to anything.
I would suggest trying to initialize MY_APP before assigning it as a value for a variable.
Since the only purpose of app.js to just initialize var MY_APP = {}; to global scope I decided to do the same in the test file, so:
var assert = require("assert");
global.MY_APP = {};
var math = require("../../js/utils/math.js");
solves the problem

How to have a file inherit exports in node.js / express.js?

I have a folder in my express.js app containing three files:
// models/one.js
exports.One = function() { return 'one'; }
// models/two.js
exports.Two = function() { return 'two'; }
// models/three.js
exports.Three = function() { return 'three'; }
I'd like to be able to use it like this:
var db = require('./models');
doSomething(db.One, db.Two, db.Three);
In other words, I want to group exports from multiple files in one variable.
I know that by default that require statement will look for models/index.js. Is there anything I could put in index.js that will allow it to inherit the exports from the other files in the directory, such as (non-working psuedocode):
// models/index.js
exports = require('./one.js', './two.js', './three.js);
Thoughts? Thanks!
See Customizing existing Module for the solution.
Or you can load all the files in a directory, e.g.
a.js:
exports.a = 1;
b.js:
exports.b = 2;
index.js: (this will require all the .js files in the same directroy and bundle them to a single object)
var fs = require('fs')
, path = require('path')
, bundle = {}
, i
, k
, mod;
fs.readdirSync(__dirname).forEach(function(filename) {
if (path.extname(filename) == '.js' &&
path.resolve(filename) != __filename) {
mod = require(path.resolve(path.join(__dirname, filename)));
for (k in mod) {
bundle[k] = mod[k];
}
}
});
module.exports = bundle;
requiring the directory you will see
{ a: 1, b: 2 }

Categories