NodeJS Passing Express res to completely different module - node.js

I have an program that susposed to load js to server side dynamically by url (for organizing js files)
app.get('/*',function(req,res){
... path etc. code
if(compare(list,path)){
const js = require('/Js/'+list.find(x => x.pageUrl == path).js)
js.run(req,res)
}
... more code there
}
but for some reason passed res doesnt work and i get res.send is not defined error
here is the other module that i get path from url and load it
exports.run = function run(req,res)
{
res.Send("test") //not defined for some reason
console.log(res) //it is not undefined, i see stuff
res.end()
}

Your code says res.Send instead of res.send.

Related

Node Js API : where the undefined comes from?

I write this code to get the array from url. this is the url : http://localhost:3000/main?a=aaa.jpg&a=bbb.jpg
And here is the code :
//Define module
var express = require('express');
var app = express();
const { exec } = require('child_process');
//extract function
function extract (req,res,next){
res.write(`filename : ${req.query.a}`); //kt page
console.log(req.query.a);//kt terminal
next();
};
//main function
function main (req,res,next){
res.write('\nkuor dok \n');
res.end();
};
app.use(extract);
app.get('/main',main);
app.listen(3000);
This is the output in terminal.
Array(2) ["aaa.jpg", "bbb.jpg"]
undefined
The question is where the undefined comes from? It affected everything i need to do. The array is perfectly fine. But suddenly undefined comes out. Can anyone help me. Thank you in advance.
I tried the code you provided above and i got only the array in the terminal
[ 'aaa.jpg', 'bbb.jpg' ]
When i tried the url in the browser i got
filename : aaa.jpg,bbb.jpg
kuor dok
as the output. i didn't get any undefined
I see that you are trying to define extract function as a middleware. It will be executed for every request
try to comment app.get:
app.use(extract);
//app.get('/main', main);
app.listen(3000);
Then try to make the request
GET: http://localhost:3000/main?a=aaa.jpg&a=bbb.jpg
you will get
[ 'aaa.jpg', 'bbb.jpg' ]
You are handling the request twice. First by the global middleware, the second time by app.get() that calls also the middleware extract before main
As I see app.get don't handle your query params and you got undefined due to an empty object try to log: req.query intead of req.query.q
function extract(req, res, next) {
res.write(`filename : ${req.query.a}`); //kt page
console.log(req.query); //kt terminal
next();
};

Node.Js promises and async/await

I am trying to use a oai-pmh harvester to harvest all articles from oai repositor and store them in a local mongo database.
I have a small demo.js file to test and print the titles on the console and it works perfectly. This is my demo.js file:
const oaipmh = require('./my_modules/harvester/harvester.js');
const urlProvider='any OAI URL repo'; // change URL here
let harvester=new oaipmh.Harvester(urlProvider);
harvester.harvest(processItem,function(err,res){
console.log(res);
});
Function processItem(item){
try{
let titles=item.metadata['oai:dc:dc']['dc:title'];
let title=(typeof titles=='object')?titles.join("\n"):titles;
console.log(title);
console.dir(item.metadata['oai_dc:dc']);
}catch(err){
// handle errors here
}
};
I am still trying to learn how to use promises and async/await and how to handle it. So far I have tried to use it inside my controller, but I am getting an error.
On my router file i have:
router.route('/doc')
.get(doc.aggregate_one);
On my controller file i have:
var Doc=require('../models/docModel);
const aoipmh=require('../../harvester/harvester');
exports.aggregate_one = async (req,res,next) => {
const urlProvider = req.header('url');
let harvester=new oaipmh.Harvester(urlProvider);
harveste.harvestAsync(urlProvider,processItemmfunction(err,res){
// do something
});
};
I want to send the URL in the header of my get instead of the barcode. When I am trying to test the GET I am receiving an UnhandledPromiseRejectionWarning: Error; Unexpected status code 400 (expected 200)
How can I use the example of the demo.js file inside my controller in order to handle the Promise?

Understanding ExpressJS application start-up

I am struggling with how application start-up works in Express. I am going to explain my use-case:
I have a configuration-Manager module which is used by all other application modules to load required configuration. I am setting configuration in app.listen:
app.listen(9000, function () {
try
{
config_manager.setSiteConfig();
console.log('settings..!!!')
}
catch(err)
{
console.log(err.stack);
}
});
In another module of the same application I call the Configuration-Manager function to load config, but it returns empty. Code is something like this:
var config_manager = require('configuration-manager');
console.log(config_manager.loadConfig()); // returns empty object {}
I am running the application using node app.js. The empty object gets printed first then ('settings..!!!'). Does Express compile the script before calling app.listen()? How do I make sure that my configuration is set before compilation/loading other files?
Express indeed first processes all statements in a file, basically anything that isn't in a function on startup.
In your case var config_manager = require('configuration-manager');
console.log(config_manager.loadConfig()); // returns empty object {} is executed before your app.listen because you are requering the config before the app.listen.
You're best off processing your configuration right after the first time it is required (if app.js is your main file, this means the first time it comes across a require statement pointing to configuration-manager in any file).
This should make your code work:
var config_manager = require('configuration-manager');
try {
config_manager.setSiteConfig();
} catch(err) {
console.log(err.stack);
}
console.log(config_manager.loadConfig()); // returns empty object {}
and then
app.listen(9000, function () {
console.log('settings..!!!', config_manager.loadConfig()) // Should correctly print your config
});
If this doesn't work the problem does not lay in the order of execution.

Calling a module function inside a Nodejs callback

I have a module that writes to a log file. (coffeescript sorry, but you get the idea!)
require = patchRequire(global.require)
fs = require('fs')
exports.h =
log: ()->
for s in arguments
fs.appendFile "log.txt", "#{s}\n", (e)->
if (e) then throw e
It works file when I call it directly. But when I call it from a callback, for example casperjs start event:
h = require('./h').h
casper = require('casper').create()
casper.start "http://google.com", ()->
h.log("hi")
casper.run()
... I always get this or similar "undefined" TyepError:
TypeError: 'undefined' is not a function (evaluating 'fs.appendFile("log.txt", "" + s + "\n", function(e) {
if (e) {
throw e;
}
})')
Googling this doesn't give many clues!
CasperJS runs on PhantomJS (or SlimerJS) and uses its modules. It is distinct from nodejs. PhantomJS' fs module doesn't have an appendFile function.
Of course you can use fs.write(filepath, content, 'a'); to append to a file if used in casper. If you still want to use your module both in casper and node then you need to write some glue code like
function append(file, content, callback) {
if (fs.appendFile) {
fs.appendFile(file, content, callback);
} else {
fs.write(file, content, 'a');
callback();
}
}
I think the problem is with the coffeescript. Try using a splat parameter instead of relying on the arguments object.
log(statements...)
If that doesn't work, you might need to look at the javascript output or try the same thing in plain JavaScript and see if you get the same error.

Configuring $.ajax with backbone on node for testing with vows

(Edited to greatly simplify)
On node I have the following server.js file.
var Backbone = require('backbone');
var Tweet = Backbone.Model.extend({});
var Tweets = Backbone.Collection.extend({
model : Tweet,
url: function () {
return 'http://search.twitter.com/search.json?q=backbone'
}
});
var myTweets = new Tweets();
myTweets.fetch();
When I run this, I get an error that says. "Cannot call method 'ajax' of undefined" (1359:14)
basically that is the result of $ being undefined. Why is it undefined? Well there are a number of intermediate steps but when the file is loaded, it is expecting "this" to be "window" in browser or "global" on server. executed on node "this" = {}.
So the question, "How do I set 'this' to global" inside the backbone.js file?
On Backbone >= 1.x, you can simply assign Backbone.$ rather than using Backbone.setDomLibrary.
Solution for Backbone < 0.9.9
The first issue you need to address is how you are running this on Node anyway. Nodejs is a server-side JS environment, but it does not include any logic for controlling a DOM. For that you need to load something like JSDom.
When you have some DOM environment set up, you can load jQuery and your code into it and it should work just like a browser.
To answer your question specifically though, loading jQuery into the global is a bit of an ugly way to do it. You should use Backbone's setDomLibrary function to set $ to what you want.
Try something like this:
if (typeof exports !== 'undefined') {
MyModels = exports;
Backbone.setDomLibrary(require('jquery'));
server = true;
} else {
MyModels = this.MyModels = {};
}
This will fail if you try to do any DOM functions though.

Resources