Function from require() throws undefined error - javascript

As a beginner to NodeJS this might be straigtforward but yet I am unable to figure out where I am going wrong
My home.js file is as follow
module.exports = function (deps) {
var sample = require('../lib/sample'), // My own library
express = require('express'),
router = express.Router();
router.get('/', function (req, res) {
op = sample.parse('hi'); // Error here
res.send(op);
});
return router;
};
Under lib folder, my sample.js code is
module.exports = function () {
function parse(text) {
return 'hello' + text;
}
return {
'sample': {
'parse': parse
}
};
};
But I get an error saying undefined is not a function on the highlighted line. Can anyone let me know what I am missing?

Since you export a function, sample will be a function now. You need to explicitly execute it to get the same object. So, you need to do something like this
var sample = require('../lib/sample')().sample
Now, the require statement returns the function, and we immediately execute it, which returns an object with sample property. Since you are interested in sample property only, we get only the sample property.
If you were planning to hide the implementation of parse from the users, I would suggest doing
function parse(text) {
return 'hello' + text;
}
module.exports = {
'parse': parse
};
Now, you are simply exporting the parse function, in an object and the code which requires this module will be able to use parse function, like you mentioned in the question.

Your module.exports evaluates to a function which when called yields the object containing the parse function you are trying to call, under some nesting. You might try restructuring your sample.js file to look like this:
function parse(text) {
return 'hello' + text;
}
module.exports = {
parse: parse
};
Unless you really need the function wrapping shown in your example. In that case you'll have to unwrap it where you import it, so something like this:
var sample = require('../lib/sample')().sample

Change your exports to:
module.exports = function () {
function parse(text) {
return 'hello' + text;
}
return {
'parse': parse
};
};

Related

How to get js function into webWorker via importScripts

I have a worker.js file:
self.importScripts('/static/utils/utils.js')
onmessage = (e) => {
let a = e.data[0]
let b = e.data[1]
let c = func1(a,b)
postMessage(c)
}
The utils.js file looks something like this:
module.exports = {
func1: function(a,b){
return a+b
}
I keep getting error:
Uncaught ReferenceError: module is not defined
at utils.js:1
Obviously require, and import and any other server side imports aren't working but I'm not sure why it's having a problem with my importScripts - https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts
The correct solution is to pack your worker with webpack. If you don't want to do that, read below.
I usually write myself a polyfill for node require:
// This will not work in normal UI thread
// None of this should make it into production
function require(moduleName) {
self.module = { exports: null };
// Nasty sttuff right here, probably should throw error instead
if (moduleName == "fs")
return null;
// This part is especially unprofessional
if (!moduleName.endsWith(".js"))
moduleName += ".js";
importScripts(moduleName);
return self.module.exports;
}
This makes use of the fact that importScripts is synchronous. Note that this will still cause errors if you try to load native node modules (eg. fs) or if other module properties are used.
Try this utils.js:
(function () {
self.func1 = function (a, b) {
return a + b
}
}());
Try to do this:
//inside worker.js
self.addEventListener("message",(event)=>{
importScripts("module.js")
utils.print1()
utils.print2()
})
//inside module.js
//setting a variable in global scope, allows worker.js to use it.
var utils = {
print1(){
console.log("This is a content from a module.")
},
print2(){
console.log("This is a another content from a module.")
}
}

Javascript property function execution

I have an model Object. One of the properties is a function to connect to an api and retrieve some values. I may have this out of order or need to create some sort of "Helper" function to do this correctly but I wanted to ask this question first.
var BuildInfo = {
arch: function getArch(){
// connect to api and return values
}
}
module.exports = BuildInfo;
How can I get this populate the arch property or do I need getArch function somewhere else and just return the results as an array to the arch property?
One strange idea comes to mind, if you really want something that looks like a property but is actually an asynchronous function call. Within an async function, you can var array = await BuildInfo.arch, assuming it looks like this:
var BuildInfo = {
get arch() {
// connect to api and return values
return someAsynchronousAPIThatReturnsAPromise()
}
}
module.exports = BuildInfo;
Demo
var BuildInfo = {
get arch() {
return Promise.resolve(['arch', 'info', 'array'])
}
}
async function getMyArchInfo() {
var array = await BuildInfo.arch
console.log(array)
}
getMyArchInfo()

How to call an external function in node js route

I am a little confused on how this works...
I am writing a node/express app and there is a function I just wrote in its own file, I need to use it in my route and I just want to call that function.
In the other file (tranformTheData.js) there is:
module.exports = {
tranformTheData:function (data){
console.log('whatever')
}
In my node app.js file I have
var formatJSON = require('./js').tranformTheData;
Can I just now use
formatJSON(data)
and utilitze this function? Or do I have to do something else, I have seen a few examples of doing this however they do not make sense to me.
You should do this:
// transformData.js
module.exports = {
formatJSON: function(data) {
console.log('whatever')
},
otherFunction: function() {
}
}
// app.js
var tranformTheData = require('./path/to/tranformTheData.js');
var formatJSON = tranformTheData.formatJSON;
var otherFunction = tranformTheData.otherFunction;
formatJSON(data); // this will work
module.exports in this case is exporting an object literal, and the object has two functions. Requiring that file and assigning it to a variable will assign that variable to the object literal, which then has access to its methods.
When you call those methods, you can then pass in whatever params you want. In the case of formatJSON, it's accepting the data param.
Make sure to add the missing closing bracket in transformTheData.js:
module.exports = {
tranformTheData: function(data) {
console.log('whatever');
}
};
Now you should be able to require the file using its filename and call the function as you are trying to do:
var formatJSON = require('./transformTheData').tranformTheData;
formatJSON(data);

Chai Sinon, should.have.been flags are undefined?

Many apologies for the title, I'm still thinking of a better way to explain this.
I'm having an issue in Chai when calling should.have.been. , where the propert always returns undefined. The weird thing is I'm doing a console.log(should.have.been) , and it prints the full object, but for some reason I can't access the flags.
example.js under test
var var BaseController = function (model, routesFn) {
var router = require('express').Router();
routesFn(router);
return router;
};
test.js
var controller = require('../lib/controller.js')
,assert = require("assert")
,chai = require('chai')
,sinon = require('sinon')
,should = chai.should();
describe('baseController', function() {
it('should have something..', function() {
var routesFn = sinon.spy();
controller(null, routesFn);
routesFn.should.have.not.been.called; //notice the 'not'.
//Should fail here, but called is undefined
assert.equal(routesFn.called, true);
});
});
So, I'm able to verify that the callback 'routesFn' is invoked by using the assert.equa(), but for some reason the called property is showing undefined. I was initially trying to create a test using the chai should have been called syntax, and later realized that my tests would pass even when I didn't have the logic implemented.
When I do a console.log of the object I see this
console.log(routesFn.should.have.not.been);
{ __flags:
{ ssfi: [Function: shouldGetter],
object:
{ [Function: proxy]
reset: [Function],
invoke: [Function: invoke],
named: [Function: named],
...
called: true
}
}
When I do a console out of 'called' , it prints undefined. Obviously I can't access the nested property.
console.log(routesFn.should.have.not.been.called); //expecting to print true
//prints
undefined
So, am I missing something in the initial setup? I was thinking I need to add something else to the 'should' variable initialization, but can't find anything on google.
Chai itself does not have support for what you are trying to do.
I presume what you call example.js should be controller.js and should be something like:
module.exports = function (model, routesFn) {
var router = require('express').Router();
routesFn(router);
return router;
};
Otherwise, I can't see how you code can work at all. Using the module above, the only thing I need to change to your test.js file is to add this after the require calls you already have, and after the call to chai.should():
var sinonChai = require('sinon-chai');
chai.use(sinonChai);
sinon-chai is what adds support for should.have.not.been.called. With this in place, your test fails as you expect.

Is it possible to render dust.js templates synchronously?

I am trying to write an adapter for a client-side HTML/JS templating system to use dust.js under the hood. Unfortunately the API expects render operations to occur synchronously: the rendered output should be returned from the render() call. Dust.js is asynchronous and passes render output to a callback function. Is there any way to work around this, either in the Dust APIs or through some crazy Javascript hack?
DustJS is only going to execute things asynchronously when the resources it needs to render (templates, partials) haven't already all been loaded.
If all the dependencies of a template are loaded before you execute that template then it'll execute synchronously (as far as I can tell anyhow). So you can do something like:
var result;
dust.render("tpl", data, function(err, res) {
result = res;
});
console.log(result); // result will actually already be filled out if dustjs didn't
// have to go look for resources somewhere.
Here is a fuller example below:
(and here is a jsfiddle link so you can run it: http://jsfiddle.net/uzTrv/1/)
<script type="text/javascript" src="dust.js"></script>
<script>
var tpl = dust.compile("Omg {#people} {.} {/people} are here! {>partial/}", "tpl");
var partial = dust.compile("I'm a partial but I've already been included so things still run {how}", "partial");
dust.loadSource(tpl);
dust.loadSource(partial);
var data = {
people: ["jim", "jane", "jack", "julie"],
how: "synchronously!"
};
var result;
dust.render("tpl", data, function(err, res) {
result = res;
});
console.log(result);
</script>
There could be cases (besides the one I mentioned) where I'm wrong... I don't know everything about dustjs.
I too wanted to have a function that accepted a context and returned the dust rendered text. Here is the solution I came up with:
// This function sets up dust template, and returns a new function "dusterFn()"
// dusterFn() can be passed a Context, and will return the rendered text.
// #param {String} text: The template text.
// #param {String} [name]: The name of the template to register with dust. If none is provided, a random number is used.
// #param {Function} [onError]: A function that is called if an error occurs during rendering.
function getDusterFn(text, name, onError) {
var dusterFn = null;
name = name || Math.floor(Math.random() * 99999).toString();
onError = onError || function (error) { };
try {
var compiled = dust.compile(text, name)
dust.loadSource(compiled);
dusterFn = function (context) {
var dustOutput = '';
dust.render(name, context, function (error, out) {
if (error) onError(error);
dustOutput = out;
});
return dustOutput;
};
} catch (e) {
// invalid template syntax
e += "\n\nPlease check your template syntax.";
throw (e);
}
return dusterFn;
}
Usage
var greetingTemplate = getDusterFn('Hello {name}, You are {age} years old!');
greetingTemplate({name: 'Jane', age: 24});
Matt's solution gave me some pointers on how to write a little wrapper that hides the "ugliness" of his solution (by "ugliness" I mean declaring variable outside of callback, assigning value inside callback and returning outside callback).
It not only wraps the hack into a little function but also binds the templateĀ“s name. I find this incredible helpful as I find myself using the same render function over and over again, but I do not want to specifiy the templateĀ“s name every time.
function templates(template) {
return function templatesWrapper(data) {
var result;
dust.render(template, data, function onRender(err, data) {
if (err) {
throw err;
}
result = data;
});
return result;
}
}
This is how to use it:
var renderHello = templates('hello.html');
renderHello({ username: 'Stackoverflow' });
// => <h1>Hello, Stackoverflow</h1>

Categories

Resources