I have three JS files running under Node.JS.
- server.js - primary server file
- bidMgr.js - helper file
- hand.js - another helper file
They are back end server Express files. All are in the same directory.
hand.js exports a function named show:
exports.show = function(hand) {...}
server.js exports a function named announceBid:
exports.announceBid = function(newBid) {...}
bidMgr.js wants to call both of these functions.
So it requires each of the modules:
const handModule = require(__dirname + "/hand.js");
const serverModule = require(__dirname + "/server.js");
bidMgr.js calls the show function as shown:
handModule.show(players['North'].hand);
But when bidMgr.js tries to call the announceBid function as shown:
serverModule.announceBid(bidStr.charAt(0) + suit);
I get this error:
/home/Documents/FullStack/WebDevelopment/bid-server/bidMgr.js:212
serverModule.announceBid(nextBid.level + nextBid.suit);
TypeError: serverModule.announceBid is not a function
I can't see any difference in how these functions are being exported and required.
Yet one works and the other does not.
I've looked at dozens of posts on StackOverflow and tried all the suggested solutions, without success.
My only guess is that the server.js code also needs to call functions exported by bidMgr.js.
That is, the server.js code includes the command:
const bidMgr = require(__dirname + "/bidMgr.js");
Could the problem be a circular dependency?
Here are the snippets of code from each of the 3 files.
I have included in the snippets the require statements which are used,
each exported function from the file, and how that function is called in a different file.
In summary:
- server.js exports announceBid(), which is called in bidMgr.js
- bidMgr.js exports processHumanBid(), which is called in server.js
- hand.js exports the Hand() constructor, which is called in bidMgr.js
All use the export/require semantics.
The call of Hand() in NewGame() in bidMgr.js works.
The call of announceBid() in processHumanBid() in bidMgr.js results in a error.
From server.js
---------------
// jshint esversion:6
const bidMgr = require(__dirname + "/bidMgr.js");
const express = require("express", "4.17.1");
const app = express();
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
var connections = [],
history = [],
lastMessageId = 0,
uptimeTimeout = 10 * 1000,
totalRequests = 0;
function removeConnection(res) {
var i = connections.indexOf(res);
if (i !== -1) {
connections.splice(i, 1);
}
console.log("Removed connection index " + i);
}
function broadcast(event, message) {
message = JSON.stringify(message);
++lastMessageId;
history.push({
id: lastMessageId,
event: event,
message: message
});
connections.forEach(function (res) {
sendSSE(res, lastMessageId, event, message);
});
}
exports.announceBid = function(newBid) {
const bidStr = newBid.level.toString() + newBid.suit;
broadcast('bid', bidStr);
}
From bidMgr.js
---------------
// jshint esversion:6
// Require the card module
const card = require(__dirname + "/card.js");
// Require the deck module
const deck = require(__dirname + "/deck.js");
// Require the hand module
const handModule = require(__dirname + "/hand.js");
// Require the player module
const playerModule = require(__dirname + "/player.js");
const serverModule = require(__dirname + "/server.js");
function processHumanBid(bidStr) {
const level = Number(bidStr.charAt(0));
const suit = bidStr.charAt(1);
nextBid = {suit: suit, level: level};
console.log("Human bid " + nextBid.level + nextBid.suit + " for " + bidder);
serverModule.announceBid(bidStr.charAt(0) + suit);
}
function newGame() {
if (!allPlayersJoined) {
console.log("Cannot start a game without all the players");
return;
}
// Rotate the Dealer
dealer = playerModule.getNextPlayer(dealer);
console.log("Dealer is " + dealer);
bidder = dealer;
// Deal the cards
var dealtHands = [];
var bridgeHands = [];
// Get the dealer to pass out all the cards into 4 piles
dealtHands = deck.dealDeck();
// Oh yeah, we are playing bridge. Create 4 bridge hands using these piles
for (let i = 0; i < 4; i++) {
bridgeHands[i] = new handModule.Hand(dealtHands[i]);
};
}
From hand.js
------------
//jshint esversion:6
// Require the card module
const suitModule = require(__dirname + "/suit.js");
// Require the card module
const card = require(__dirname + "/card.js");
exports.Hand = function(dealtCards) {
this.handCards = [...dealtCards];
this.handCards.sort(function(a, b) {
if (a.index < b.index) {
return -1;
}
if (a.index > b.index) {
return 1;
}
// a must be equal to b
return 0;
});
this.hcPts = calcHCP(dealtCards);
calcDistribution(this, dealtCards);
this.totalPts = calcTotalPts(this);
this.openingBid = calcOpenBid(this);
this.player = null;
};
I suggest that you don't use from call a function in the server.js (announceBid). for send response to client you can use a file this like:
apiResponse.js :
'use sctrict';
var HttpStatus = require('http-status-codes');
exports.sendSucces = function (res, data) {
try {
if (res) {
if(data)
res.status(HttpStatus.OK).json(data);
else
res.status(HttpStatus.OK).send();
}
} catch (error) {
//log error
}
}
Related
Can someone give me a hand with converting the following code from console output to file output? I'm struggling with logging and the asynchronous nature of Node. The script works great in a console, but I'd like to pipe the sorted output into individual server sections within a file with STDERR going to another file.
var rexec = require('remote-exec');
var fs = require('fs');
var lineReader = require('line-reader');
var streamBuffers = require('stream-buffers');
var _ = require('lodash');
var conn_options = {
port: 22,
username: '*****',
privateKey: fs.readFileSync('R:/nodeJS/sshkey.priv')
}
// something that dumps out a bunch of data...
var cmds = ['df']
var filename = 'servers.txt';
lineReader.eachLine(filename,function(line,last,cb){
var buffer = new streamBuffers.WritableStreamBuffer();
var my_conn_options = _.clone(conn_options);
rexec(line,cmds,my_conn_options,function(err){
if (err) {
console.log(line, err);
} else {
console.log('>>>> Start: ' + line + '<<<<')
console.log(buffer.getContentsAsString());
console.log('>>>> End: ' + line + '<<<<')
};
});
if (last) {
cb(false); // stop reading
} else {
cb();
}
});
check this example, that should help..
var fs = require('fs');
var util = require('util');
var logFile = fs.createWriteStream('log.txt', { flags: 'a' });
// Or 'w' to truncate the file every time the process starts.
var logStdout = process.stdout;
console.log = function () {
logFile.write(util.format.apply(null, arguments) + '\n');
logStdout.write(util.format.apply(null, arguments) + '\n');
}
console.error = console.log;
I need to export all things (function and prototype) from one file (name:config.js) to another file (name:index.js) that will use them
I need to create ws in Javascript with Node.js on "Sublime",
and the error said when in ran my code at cmd that 'plus' in not defined.
code :(config.js)-first file
var Ranking=function(){
this.rank= 5;
events.EventEmitter.call(this);
};
var printName=function(){
console.log("spa name is: sea spa");
};
Ranking.prototype.plus =function(sum){
this.rank += sum;
this.emit("change");
};
Ranking.prototype.minus =function(sum){
this.rank -= sum;
this.emit("change");
};
var addingStar=function(){
console.log("the ranking is: " + this.rank);
};
var changeNoZero=function(){
if(this.rank<0){
console.log("bad reviews " + this.rank);
}
};
module.exports=Ranking;
index.js -second file
var events = require('events');
var util = require('util');
var Ranking = require('./config');
var ranking = new Ranking();
util.inherits(Ranking ,events.EventEmitter);
ranking.on("change",printName);
ranking.on("change",addingStar);
ranking.on("change",changeNoZero);
ranking.plus(1);
ranking.minus(6);
ranking.plus(3);
You can try something as below :
Config.js file ----
var defaultValues = module.exports
defaultValues.GetApiURL = function () {
var apiURL = "http://localhost:1000/api/"
return apiURL;
}
index.js ----
var defaultValues = require('./config.js');
var apiUrl= defaultValues.GetApiURL();
I am trying the learn younode workshop, the make it modular step to be precise. I wrote the code in the link and am getting the "error in the title". I have checked brackets and parenthesis but can not seem to find where i got it wrong. Any help would be appreciated (i just started with node).
My code is this and you can find it also at this link:
http://pastebin.com/G8x2GH7h
module.exports = function (directoryPath, extention, function(error, arrayOfNames) {
var fs = require('fs');
var path = require('path');
var FileNamesArray = [];
fs.readdir(directoryPath,function (error,list){
list.forEach(function (file) {
if (path.extname(file) === '.' + extention) {
FileNamesArray.push(file);
}
});
});
return FileNamesArray;
}){
return ArrayOfNames;
}
Your problem is that you are declaring function inside of function declaration.
It should be like this
exports.functionName = function() {
// your code
};
And then In you app.js you can use
var abc = require('path to file name');
abc.functionName();
example
// square.js
var PI = Math.PI;
exports.area = function (r) {
return PI * r * r;
};
exports.circumference = function (r) {
return 2 * PI * r;
};
// app.js
var square = require("./square.js");
var mySquare = square(2);
console.log('The area of my square is ' + mySquare.area());
Remove the anonymous function inside your function and hopefully it should work for you.
You are missing the title of you function in the export section, should be in this way:
module.exports = {
getFileNamesList : function (directoryPath, extention, function(error, arrayOfNames) {
var fs = require('fs');
var path = require('path');
var FileNamesArray = [];
fs.readdir(directoryPath,function (error,list){
list.forEach(function (file) {
if (path.extname(file) === '.' + extention) {
FileNamesArray.push(file);
}
});
});
return FileNamesArray;
}){
return ArrayOfNames;
}
}
Half a year ago I wrote a little multiplayer game in node.js and with socket.io. Now I'm trying to improve it and one of my improvements is breaking up the code into modules (btw. I'm using expressjs 4.4 and socket.io 1.0). I have a player queue which handles the order of the connected players. Everything went pretty fine until I got stuck with socket.io: I'd like to handle the (dis-)connection listeners in the player queue while I'd like to put all the game related listeners in my game module. I tried a couple of things including Using socket.io from a module and What's the correct way to pass a Socket.IO socket between modules? none of which I brought to work. Currently I'm passing the io object from:
io = require("socket.io")(server);
Am I missing something?
My code:
PlayerManager.js
var log = require("npmlog"),
Player = require("./Model/Player").Player;
var playerIo;
var PlayerManager = (function() {
var self;
function PlayerManager(eventEmitter, io) {
log.info("PlayerManager", "loading PlayerManager");
self = this;
this.eventEmitter = eventEmitter;
this.io = io;
this.playerQueue = [];
this.players = [];
this.setSocketListeners();
}
PlayerManager.prototype.setSocketListeners = function() {
log.info("PlayerManager", "loading SocketListeners");
playerIo = this.io.of("/player").on("connection", function(socket) {
log.info("PlayerManager", "Player " + socket.id + " has connected");
socket.on("disconnect", function() {
log.info("PlayerManager", "Player " + socket.id + " has disconnected.");
self.removePlayer(socket.id);
});
self.addPlayer(new Player(socket));
});
};
PlayerManager.prototype.addPlayer = function(player) {
log.info("PlayerManager", "Pushing Player " + player.socket.id + " to Queue. Current position: " + this.playerQueue.length);
this.playerQueue.push(player);
};
PlayerManager.prototype.removePlayer = function(id) {
log.info("PlayerManager", "Removing Player " + id + " from Queue");
var player = this.getPlayerById(id);
if (!player) {
return;
}
this.playerQueue.splice(this.playerQueue.indexOf(player), 1);
};
PlayerManager.prototype.getPlayers = function() {
log.info("PlayerManager", "Choosing players (length of queue: " + this.playerQueue.length + ")");
this.players = [];
if (this.playerQueue.length >= 1) { //should be changed to 2 in PROD
var player;
for (var i = 0; i < 4; ++i) {
player = this.playerQueue.shift();
if (player !== undefined && !player.socket.disconnected) {
player.socket.join("players");
this.players.push(player);
}
}
return this.players;
} else {
return false;
}
};
PlayerManager.prototype.onGameFinished = function() {
var player;
while (this.players && this.players.length > 0) {
player = this.players.shift();
player.socket.leave("players");
log.info("GameManager", "players size: " + self.players.length);
}
};
PlayerManager.prototype.getPlayerById = function(id) {
for (var i = 0; i < this.playerQueue.length; ++i) {
if (this.playerQueue[i].socket.id === id) {
return this.playerQueue[i];
}
}
return false;
};
return PlayerManager;
})();
exports = module.exports = PlayerManager;
Game.js
var log = require("npmlog");
var config = require("./config");
var Duck = require("./Model/Duck").Duck;
var Game = (function() {
var self;
function Game(eventEmitter, io, players) {
log.info("Game", "loading ...");
self = this;
this.io = io;
this.eventEmitter = eventEmitter;
this.players = players;
setInterval(function() {
self.io.to("players").emit("blub");
});
// ...
return Game;
})();
exports = module.exports = Game;
and for completeness:
index.js (the client)
define(["socketio"], function(io) {
var socket = io("/player");
socket.on("blub", function() {
console.log("blub");
});
setInterval(function() {
socket.emit("blub");
}, 1000);
});
After one year it's time to clean up and share insights I've gained over that period.
Having socket.io-related code spread all over the project is bad design (or code from any other library for that matter). If you ever would have to change the wrapper library, you'd have to do so in many places in your code base. The better approach is to restrict usage of socket.io to a thin layer where all the communication to and from websockets is done. From there on you'd use another layer of messaging: your own. Node.js' own EventEmitter is everything you'd need for the job.
I want to configure an app that requires that I run node generate.js and node generate_texts_index.js on node's command prompt. These files are to build the data required for the app to work. When i run these files locally the app works in my browser. Now I have the same set of files located on my server, how can I run node generate.js when the files are on my server at www.example.com. I am new to node js. Thanks!
Here's what generate.js looks like
// MODULES
var fs = require('fs'),
path = require('path'),
bibleData = require('bible_data');
//console.log( bibleData.getBookInfoByUnboundCode('40N') );
//return;
// VARS
var
baseOutput = '../../app/content/texts/',
baseInput = 'input',
createIndex = true;
console.log('\r\r\r');
function convertFolder(inputPath) {
var infoFilePath = path.join(inputPath, 'info.json'),
startDate = new Date();
if (fs.existsSync(infoFilePath)) {
var info = JSON.parse( fs.readFileSync(infoFilePath, 'utf8') ),
generatorName = info.generator,
generator = require('generate_' + generatorName),
outputPath = path.join(baseOutput, info['id']),
indexOutputPath = path.join(outputPath, 'index');
console.log('-----');
console.log(info['name'], outputPath);
// remove existing data
if (fs.existsSync(outputPath)) {
var files = fs.readdirSync(outputPath);
// DELETE all files
files.forEach(function(data) {
var filePath = path.join(outputPath, data);
if (fs.statSync(filePath).isFile()) {
fs.unlinkSync(filePath);
}
});
} else {
fs.mkdirSync(outputPath);
}
// index data
if (createIndex) {
if (fs.existsSync(indexOutputPath)) {
var files = fs.readdirSync(indexOutputPath);
// DELETE all files
files.forEach(function(data) {
var filePath = path.join(indexOutputPath, data);
if (fs.statSync(filePath).isFile()) {
fs.unlinkSync(filePath);
}
});
} else {
fs.mkdirSync(indexOutputPath);
}
}
generator.generate(inputPath, outputPath, indexOutputPath, info, createIndex);
var endDate = new Date();
console.log('time: ' + MillisecondsToDuration(endDate - startDate));
}
}
function convertFolders() {
var files = fs.readdirSync(baseInput),
startDate = new Date();
// DO ALL
for (var f in files) {
var folder = files[f],
inputPath = path.join(baseInput, folder);
convertFolder(inputPath);
}
var endDate = new Date();
console.log('TOTAL: ' + MillisecondsToDuration(endDate - startDate));
}
function MillisecondsToDuration(n) {
var hms = "";
var dtm = new Date();
dtm.setTime(n);
var h = "000" + Math.floor(n / 3600000);
var m = "0" + dtm.getMinutes();
var s = "0" + dtm.getSeconds();
var cs = "0" + Math.round(dtm.getMilliseconds() / 10);
hms = h.substr(h.length-4) + ":" + m.substr(m.length-2) + ":";
hms += s.substr(s.length-2) + "." + cs.substr(cs.length-2);
return hms;
}
// START
// make /texts/ folder
if (!fs.existsSync(baseInput)) {
fs.mkdirSync(baseInput);
}
// process 1 or more folders
if (process.argv.length > 2) {
var folders = process.argv[2].split(',');
folders.forEach(function(folder) {
convertFolder(baseInput + '/' + folder);
});
} else {
convertFolders();
}
You need to run Node on your server.
Generally this would be done by using SSH to connect to the server and configuring it in the same way that you would for any other computer.
You won't be able to do this on low end hosting. You need to look at hosting that specifically advertises Node support, or a VPS or better.