When I run this code I want to be printed as "Mohammed said: hi guys"
but it comes to an error
which is #person is not a function.
Why it is?
var events = require('events');
var util = require('util');
var person = function(name){
this.name = name;
};
util.inherits(person, events.EventEmitter);
var mohammed = new person('mohammed');
var tahir = new person('tahir');
var taha = new person('taha');
var people = ['mohammed', 'tahir', 'taha'];
people.forEach(function(person){
person.on('speak', function(msg){
console.log(person.name + 'said:' + msg);
});
});
mohammed.emit('speak', "Hi guys");
tahir.emit('speak', "i want a chicked");
can anyone fix this? and let me know where I am gone wrong and why?
You're trying to call an .on method on a string in the people array.
You'll need to put the person objects you've created, not strings, into the people array:
var people = [mohammed, tahir, taha];
instead of
var people = ['mohammed', 'tahir', 'taha'];
Related
I have a large xml which is a combination of xml documents. I'm trying to use a nodejs xml splitter and respond back with the number of documents i have found.
My code looks something like this. I'm looking to get the number of documents outside the function(in the last line). Is there something I can do to achieve this?
var XmlSplit = require('./xmlsplitter.js')
const fs = require('fs')
var xmlsplit = new XmlSplit()
var no_of_docs = 0
var inputStream = fs.createReadStream('./files/input/test.xml')
inputStream.pipe(xmlsplit).on('data', function(data,callback) {
var xmlDocument = data.toString();
no_of_docs = no_of_docs + 1;
})
inputStream.pipe(xmlsplit).on('end', function(){
console.log('Stream ended');
console.log(no_of_docs); <-- This prints the correct value but the value is lost as soon as we exit this.
});
console.log("This is outside the function " + no_of_docs); <-- I need the value here.
It took me a while to figure out what the problem was, but I'm wondering why it's acting like that.
Using this code, the variables player, players and socket will be undefined, causing errors.
var player = Player(socket.id, socket);
socket.on('joinHost', function(data) {
var gameID = data;
player.gameID=gameID;
var game = GAME_LIST[gameID];
game.players[socket.id]=player;
var players = game.players;
for (var p in players){
var player = players[p];
var socket = player.socket;
socket.emit('playerJoined');
}
});
Avoiding the declarations of variables with same names makes it all work correctly.
var player = Player(socket.id, socket);
socket.on('joinHost', function(data) {
var gameID = data;
player.gameID=gameID;
var game = GAME_LIST[gameID];
game.players[socket.id]=player;
var tempPlayers = game.players;
for (var p in tempPlayers){
var tempPlayer = tempPlayers[p];
var tempSocket = tempPlayer.socket;
tempSocket.emit('playerJoined');
}
});
The interesting part is, when I ran the first code, it says the player in the line player.gameID=gameID is undefined, while if I removed the code which is after player.gameID=gameID, the player was defined. Basically, the code after player.gameID=gameID caused the player to be undefined.
So, why is this happening?
When you declare var player = players[p]; it is declared for the whole function scope (the for loop doesn't has a scope of it's own).
The names in the current scope are evaluated all in the beginning, before executing the function body.
So when function(data) is called, the name player is overridden in that scope even before var gameID = data; is executed.
A minimal example:
> var x = 'foo';
> f = function() { console.log(x); var x = 'bar'; }
> f()
undefined
Javascript moves variables's declaration to the top of the scope they were defined and gives them an undefined initial value but keeps assignment in place. This is called hoisting
Your code is equivalent to :
var player = Player(socket.id, socket);
socket.on('joinHost', function(data) {
var gameID; // undefined
var game; // undefined
var players; // undefined
var player; // undefined
var socket; // undefined
gameID = data;
player.gameID=gameID; // can't set property 'gameID' of undefined
game = GAME_LIST[gameID];
game.players[socket.id]=player; // is undefined since 'player' is undefined at this stage
players = game.players; // undefined
for (var p in players){
player = players[p];
socket = player.socket;
socket.emit('playerJoined');
}
});
I'm trying to delete all nodes with a date greater than '2017-04-05' with a bulk operation with a firebase function. Can you spot what I'm doing wrong here?
The 2 nodes that should get deleted are the ones in red:
Here's the code that is failing - can you see what's wrong? Also, I'm concerned about the performance of this (I'll only run it once in a while though). If there are millions of games in the list, should that concern me if I only run this once a day?
exports.remove = functions.https.onRequest((req, res) => {
const deleteBeforeDate = req.query.deleteBeforeDate;
var ref = admin.database().ref('games');
var keysToDelete = {};
for (var game in this.games) {
var date = items[i]['.date'];
if(date.value > '2017-04-05'){
keysToDelete[game.key] = null;
}
}
this.ref.update(keysToDelete);
});
Thank you very much,
Mike
To determine the keys to delete, you'll need to attach a listener. Since that is needed, you might as well create a query that selects the correct children and deletes only those:
var ref = admin.database().ref('games');
var deleteAfterDate = ref.orderByChild('date').startAt('2017-04-05');
deleteAfterDate.once('value').then(function(snapshot) {
var updates = {};
snapshot.forEach(function(child) {
updates[child.key] = null;
});
ref.update(updates);
});
i'm trying to understand and use promisification (bluebird) in nodejs
var io = require('socket.io')(8080);
var players = io.of('/players');
var coaches = io.of('/coaches');
var managers = io.of('/managers');
io.listen();
instead of doing this:
players.emit('name', data);
coaches.emit('name', data);
managers.emit('name', data);
i want to be able to write something like this:
var promises =
Array.of(players, coaches, managers)
.map(function(nsp){
return nsp.emitAsync('name', data)
});
Promise.all(promises).then(function(){console.log('ok')});
is this even posible ?
I think I'm having a difficult time wrapping my head around the scope of the following code:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
this.time = time;
this.tick = function() {
this.emit('tick');
setTimeout(this.tick(), this.time);
};
}
util.inherits(Ticker, EventEmitter);
var newTicker = new Ticker(1000);
newTicker.on('tick', function() { console.log("TICK"); });
newTicker.tick();
What ends up happening, is that the "tick" gets called many, many times filling up the stack without the setTimeout actually setting the timeout to one second.
Could any explain to me what's going on?
EDIT: I looked a little bit more, and I still couldn't figure out the issue of scope, really.
What I ended up doing was following the solution that was given for the problem, which I tried to solve by way of setTimeout().
The solution given was:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
var self = this;
this.time = time;
setInterval(function() {
self.emit('tick');
}, self.time);
};
util.inherits(Ticker, EventEmitter);
var ticker = new Ticker(1000);
ticker.on('tick', function() { console.log("TICK"); });
It does make more sense to me... What I'm wondering now is: Do inner functions and objects in javascript not keep track of their parent's scope and variables?
Your initial problem is that you were calling this.tick inside your setTimeout:
setTimeout(this.tick(), this.time);
Instead, you want to pass a reference to the this.tick function:
setTimeout(this.tick, this.time);
This fixes the problem for the first loop, but the second call to tick (which comes from the setTimeout) is not bound to the correct scope; so, you can bind the function reference to the current value of this using bind:
setTimeout(this.tick.bind(this), this.time);
(You can also use the self trick if you prefer.)
So, the full working program is:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
this.time = time;
this.tick = function() {
this.emit('tick');
setTimeout(this.tick.bind(this), this.time);
};
}
util.inherits(Ticker, EventEmitter);
var newTicker = new Ticker(1000);
newTicker.on('tick', function() { console.log("TICK"); });
newTicker.tick();