socket.emit doesn't work inside setTimeout() nodejs - javascript

The first playerHandler.nextTurn() will return the first player from the player list with his corresponding socket id .But calling currsocket.emit won't do anything. I then tried io.emit which emits to all other players . Since I have max of 2 players , the event doesn't trigger inside the first player client socket.
Calling the second player currsocket.emit would work properly .
It seems there is some issue with the setTimeout() , since in my other code , this works without any issues (without timeout).
socket.on('add-player', (player) => {
//console.log('socket add player hits');
console.log("add user name :" + player.name);
//add the new player
var newPlayer = { 'id': socket.id.toString(), 'name': player.name };
//dont use this. for the var declared above
var canWeKeepHim = { value: false };
var package = playerHandler.methods.addNewPlayer(newPlayer, canWeKeepHim);
//on successful addition of new player add him to gameroom socket room
if (canWeKeepHim.value) {
socket.join('gameroom');
console.log(player.name + 'joined socket room');
}
socket.emit('add-player-message', { type: 'success-message', package: package });
io.emit('add-player-list', playerHandler.methods.getNewPlayer());
//is the async nature of socket events a problem , the start-game never seems to be true;
if (GameHandler.currentGameState == GameHandler.yetToStartGame && playerHandler.methods.doWeHaveMaxPlayers()) {
GameHandler.changeCurrentGameState(GameHandler.gameHasStarted);
var delay = 3000;
io.to('gameroom').emit('start-game', { value: true, delay: delay });
//if the game state is still gameHasStarted after delay then fire the gameplay events
GameHandler.gameArenaRedirectTimer = setTimeout(() => {
if (GameHandler.currentGameState == GameHandler.gameHasStarted) {
console.log('hey this works after 10s');
var currentPlayerTurn = playerHandler.methods.nextTurn();
currentPlayerTurn = playerHandler.methods.nextTurn();;
var currsocket = io.sockets.sockets[currentPlayerTurn.id];
currsocket.emit('next-turn', { myturn: true });
//console.log(io.sockets.so)
// io.emit('next-turn', { myturn: false, playerName: currentPlayerTurn.name });
//io.to('gameroom').emit('next-turn', { myturn: false, playerName: currentPlayerTurn.name });
}
}, delay);
}
});

I found out that moving the setTimeout out of the socket.on event listener callback and out of the io.on event listener fixed the issue.
function startCountDownToStartGame(callback, delay, arg) {
if (GameHandler.currentGameState == GameHandler.gameHasStarted) {
GameHandler.gameArenaRedirectTimer = setTimeout(callback, delay, arg);
}
};
io.on('connection', (socket) => {
console.log('user connected :' + socket.id);
socket.on('disconnect', function () {
console.log('user disconnected');
//TODO : remove player from the player list once hes disconnected
});
socket.on('add-player', (player) => {
//console.log('socket add player hits');
console.log("add user name :" + player.name);
//add the new player
var newPlayer = { 'id': socket.id.toString(), 'name': player.name };
//dont use this. for the var declared above
var canWeKeepHim = { value: false };
var package = playerHandler.methods.addNewPlayer(newPlayer, canWeKeepHim);
//on successful addition of new player add him to gameroom socket room
if (canWeKeepHim.value) {
socket.join('gameroom');
console.log(player.name + 'joined socket room');
}
socket.emit('add-player-message', { type: 'success-message', package: package });
io.emit('add-player-list', playerHandler.methods.getNewPlayer());
if (GameHandler.currentGameState == GameHandler.yetToStartGame && playerHandler.methods.doWeHaveMaxPlayers()) {
GameHandler.changeCurrentGameState(GameHandler.gameHasStarted);
var delay = 3000;
io.to('gameroom').emit('start-game', { value: true, delay: delay });
delay += 1000;// this is a temp fix
//it seems calling the settimeout within the socket.on will somehow affect the emit functions for all other socket
//other than the current socket , by placing the settimeout outside , it fixed the problem .
startCountDownToStartGame((socket) => {
var currentPlayerTurn = playerHandler.methods.nextTurn();
var currsocket = io.sockets.sockets[currentPlayerTurn.id];
currsocket.emit('next-turn', { myturn: true });
currsocket.broadcast.to('gameroom').emit('next-turn', { myturn: false, playerName: currentPlayerTurn.name });
}, delay, socket);
}
});
}

Try passing socket to your setTimout
GameHandler.gameArenaRedirectTimer = setTimeout((socket) => {
if (GameHandler.currentGameState == GameHandler.gameHasStarted) {
console.log('hey this works after 10s');
var currentPlayerTurn = playerHandler.methods.nextTurn();
currentPlayerTurn = playerHandler.methods.nextTurn();;
var currsocket = io.sockets.sockets[currentPlayerTurn.id];
currsocket.emit('next-turn', { myturn: true });
//console.log(io.sockets.so)
// io.emit('next-turn', { myturn: false, playerName: currentPlayerTurn.name });
//io.to('gameroom').emit('next-turn', { myturn: false, playerName: currentPlayerTurn.name });
}
}, delay,socket);

Related

Redirect after the flash message disappears in Angular2

I have a function which calls a service.
submitPost(value:any)
{
this._adminLogin.postAdminLogin(this.adminLoginmodel).subscribe(
data => {
this.responseStatus = data;
if(this.responseStatus.status == 1)
{
localStorage.setItem('admin_id', this.responseStatus.detail.id);
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-success', timeout: 5000 });
top.location.href = 'admin/dashboard';
}
else
{
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-danger', timeout: 2000 });
}
},
err => {
console.log(err)
},
() => {}
);
this.status = true;
}
My concern is with this section of code:-
if(this.responseStatus.status == 1)
{
localStorage.setItem('admin_id', this.responseStatus.detail.id);
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-success', timeout: 5000 });
top.location.href = 'admin/dashboard';
}
Is there any way by which the redirect action could take place after the flash message disappears after 5000 ms? Something like this:-
if(this.responseStatus.status == 1)
{
localStorage.setItem('admin_id', this.responseStatus.detail.id);
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-success', timeout: {function(){ top.location.href = 'admin/dashboard'; }, 5000 });
}
The following code should navigate after the message disappears. Yout flashMessage will be displayed for 5000 ms and your navigate should happen after 7000ms
if(this.responseStatus.status == 1)
{
localStorage.setItem('admin_id', this.responseStatus.detail.id);
this._flashMessagesService.show(this.responseStatus.message, { cssClass: 'alert-success', timeout: 5000 });
setTimeout(()=>{
top.location.href = 'admin/dashboard';
},7000);
}
I would do this by having the _flashMessagesService.show() return an Observable.
In the _flashMessageService, something like this:
myObserver : Observer<any>
function show(){
// do stuff
return Observable.create(observer =>{
this.myObserver =observer;
});
}
When you're ready to resolve the Observable, you can do:
this.myObserver.next('Possibly some value here');
this.myObserver.complete();
In your invoking code
this._flashMessagesService.show()
.subscribe(result=> { top.location.href = 'admin/dashboard'});}
I have been working on something similar.
An alternate approach, perhaps simpler is to just use Observable.timer in your main component:
Observable.timer(5000).subscribe(result=> { top.location.href = 'admin/dashboard'});
I prefer the first way, because it is contingent on the flashMessage service deciding when the flash message goes away, not on a hard coded time value.

StateParams passed through function not working using meteor

Here is my function used to retrieve data from the database depending on the parameter idCats:
this.getSubcat = function(){
//Load products on scroll.
this.subscribe('SubcatIndex', () => [ $stateParams.idCats, self.loaded ], {
onReady: function() {
Meteor.call('allSubcats', $stateParams.idCats, function(err, count) {
self.allsubcats = count;
self.limit = self.loaded;
console.log("Test Log: " + $stateParams.idCats);
self.subcats = Products.find({
catLinkID : $stateParams.idCats
},{
fields: {
_id: true,
name: true,
catLinkID: true,
idCat: true,
image: true,
listingsCount: true,
productOffersCount: true,
productSoldCount: true
}
}).fetch();
window.localStorage.setItem('subcats', JSON.stringify(self.subcats) );
self.contentLoaded = true;
self.noPosts = 'No posts available.';
$ionicLoading.hide();
return;
});
},
onStop: function(err){
if(err){
self.contentLoaded = true;
self.noPosts = "No internet connection.";
console.log(JSON.stringify(err));
return;
}
}
});
}
this.getSubcat();
When i change this line:
self.subcats = Products.find({
catLinkID : $stateParams.idCats
}
To:
self.subcats = Products.find({
catLinkID : 7 // 7 for example
}
It is working well ! But as soon as I replace it with $stateParams.idCats, I receive this message coming from the function: No posts available.
Note that there are products using the idCats: 7.
When I log it:
console.log("Test Log: " + $stateParams.idCats);
This returns the same number: Test Log: 7.
If you have any suggestion or a starting point to solve this issue, it will be welcome !
Notice that there are no error in the Console (Both server and client side).
Thank you.

How to create click listener in each chrome notification?

I want to create multiple chrome-extension-notifications listener which has each click listener. but I couldn't make it my way.
When I click in one notification, all notifications listener were played. this is basic_notification.js
function notifyMe() {
var notificationId = 'notId1';
var notificationId2 = 'notId2';
var notificationId3 = 'notId3';
var opt = {
type: 'basic',
iconUrl: 'http://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png',
title: 'anyTitle',
message: 'anyString'
};
chrome.notifications.create(notificationId, opt , function(notificationId) {
console.log(notificationId);
});
chrome.notifications.create(notificationId2, opt , function(notificationId2) {
console.log(notificationId2);
});
chrome.notifications.create(notificationId3, opt , function(notificationId3) {
console.log(notificationId3);
});
}
This code can create 3 notifications in once.
and I will write listener in each chrome-extension-notifications.
chrome.notifications.create(notificationId, opt , function(notificationId) {
chrome.notifications.onClicked.addListener(notificationClicked);
console.log(notificationId);
});
function notificationClicked() {
console.log("The notification1 was clicked");
}
This is all code : notification.js
function notifyMe() {
var notificationId = 'notId1';
var notificationId2 = 'notId2';
var notificationId3 = 'notId3';
var opt = {
type: 'basic',
iconUrl: 'http://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png',
title: 'anyTitle',
message: 'anyString'
};
chrome.notifications.create(notificationId, opt , function(notificationId) {
chrome.notifications.onClicked.addListener(notificationClicked);
console.log(notificationId);
});
chrome.notifications.create(notificationId2, opt , function(notificationId2) {
chrome.notifications.onClicked.addListener(notificationClicked2);
console.log(notificationId2);
});
chrome.notifications.create(notificationId3, opt , function(notificationId3) {
chrome.notifications.onClicked.addListener(notificationClicked3);
console.log(notificationId3);
});
}
function notificationClicked() {
console.log("The not1 was clicked");
}
function notificationClicked2() {
console.log("The not2 was clicked");
}
function notificationClicked3() {
console.log("The not3 was clicked");
}
I want to have only one when I press one. What should I do?

Using setInterval and JavaScript

I'm working with Notification API but i can't make it work with SetInterval(), can somebody point out what i'm doing wrong. As long as i click the event, the notification only displays once. Here is my code:
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('notifyBtn').addEventListener('click', function() {
if (!('Notification' in window)) {
alert('Web Notification is not supported');
return;
} else {
setInterval(Notification.requestPermission(function(permission) {
var notification = new Notification("Hi there!", {
body: 'I am here to talk about HTML5 Web Notification API',
icon: 'icon.png',
dir: 'auto'
});
setTimeout(function() {
notification.close();
}, 2000);
}),5000);
}
;
});
});
I'm really stucked here, please halp.
You need to pass valid callback to setInterval(). Instead, you are passing the result of some method. Try this:
setInterval(function () {
Notification.requestPermission(function(permission) {
var notification = new Notification("Hi there!", {
body: 'I am here to talk about HTML5 Web Notification API',
icon: 'icon.png',
dir: 'auto'
});
setTimeout(notification.close, 2000);
})}, 5000);
Bonus: see how I simplified your setTimeout callback, by just passing the notification.close method itself, instead of calling it in anonymous function. Much cleaner.
Wrap your method in anonymous function
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('notifyBtn').addEventListener('click', function() {
if (!('Notification' in window)) {
alert('Web Notification is not supported');
return;
} else {
setInterval(function(){Notification.requestPermission(function(permission) {
var notification = new Notification("Hi there!", {
body: 'I am here to talk about HTML5 Web Notification API',
icon: 'icon.png',
dir: 'auto'
});
setTimeout(function() {
notification.close();
}, 2000);
})},5000);
}
;
});
});
I found something like this :
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('notifyBtn').addEventListener('click', function() {
if (!('Notification' in window)) {
alert('Web Notification is not supported');
return;
} else {
setInterval(notify, 5000);
}
});
function notify() {
Notification.requestPermission(function(permission) {
var n = new Notification("Hi there!", {
body: 'I am here to talk about HTML5 Web Notification API',
icon: 'icon.png',
dir: 'auto'
})
setTimeout(function(){n.close()}, 2000)
})
}

How can I remove a whole IndexedDB database from JavaScript?

How can one remove a whole IndexedDB database from JavaScript, as opposed to just an object store? I'm using the IndexedDB shim, which may use WebSQL as its backend.
I'd mainly like to know how to do this for the PhantomJS (headless) browser, although Chrome, Safari (on iPad) and IE10 are other important browsers.
As far as I can tell, one should use indexedDB.deleteDatabase:
var req = indexedDB.deleteDatabase(databaseName);
req.onsuccess = function () {
console.log("Deleted database successfully");
};
req.onerror = function () {
console.log("Couldn't delete database");
};
req.onblocked = function () {
console.log("Couldn't delete database due to the operation being blocked");
};
I can confirm that it works with PhantomJS 1.9.0 and Chrome 26.0.1410.43.
I found that the following code works OK but to see the DB removed in the Chrome Resources Tab I have had to refresh the page.
Also I found I had problems with the Chrome debug tools running while doing transactions. Makes it harder to debug but if you close it while running code the code seems to work OK.
Significant also is to set a reference to the object store when opening the page.
Obviously the delete part of the code is in the deleteTheDB method.
Code derived from example provided by Craig Shoemaker on Pluralsight.
var IndDb = {
name: 'SiteVisitInsp',
version: 1000,
instance: {},
storenames: {
inspRecords: 'inspRecords',
images: 'images'
},
defaultErrorHandler: function (e) {
WriteOutText("Error found : " + e);
},
setDefaultErrorHandler: function (request) {
if ('onerror' in request) {
request.onerror = db.defaultErrorHandler;
}
if ('onblocked' in request) {
request.onblocked = db.defaultErrorHandler;
}
}
};
var dt = new Date();
var oneInspRecord =
{
recordId: 0,
dateCreated: dt,
dateOfInsp: dt,
weatherId: 0,
timeArrived: '',
timeDeparted: '',
projectId: 0,
contractorName: '',
DIWConsultant: '',
SiteForeman: '',
NoOfStaffOnSite: 0,
FileME: '',
ObservationNotes: '',
DiscussionNotes: '',
MachineryEquipment: '',
Materials: ''
};
var oneImage =
{
recordId: '',
imgSequence: 0,
imageStr: '',
dateCreated: dt
}
var SVInsp = {
nameOfDBStore: function () { alert("Indexed DB Store name : " + IndDb.name); },
createDB: function () {
openRequest = window.indexedDB.open(IndDb.name, IndDb.version);
openRequest.onupgradeneeded = function (e) {
var newVersion = e.target.result;
if (!newVersion.objectStoreNames.contains(IndDb.storenames.inspRecords)) {
newVersion.createObjectStore(IndDb.storenames.inspRecords,
{
autoIncrement: true
});
}
if (!newVersion.objectStoreNames.contains(IndDb.storenames.images)) {
newVersion.createObjectStore(IndDb.storenames.images,
{
autoIncrement: true
});
}
};
openRequest.onerror = openRequest.onblocked = 'Error'; //resultText;
openRequest.onsuccess = function (e) {
//WriteOutText("Database open");
IndDb.instance = e.target.result;
};
},
deleteTheDB: function () {
if (typeof IndDb.instance !== 'undefined') {
//WriteOutText("Closing the DB");
IndDb.instance.close();
var deleteRequest = indexedDB.deleteDatabase(IndDb.name)
deleteRequest.onblocked = function () {
console.log("Delete blocked.");
}
deleteRequest.onerror =
function () {
console.log("Error deleting the DB");
//alert("Error deleting the DB");
};
//"Error deleting the DB";
deleteRequest.onsuccess = function () {
console.log("Deleted OK.");
alert("*** NOTE : Requires page refresh to see the DB removed from the Resources IndexedDB tab in Chrome.");
//WriteOutText("Database deleted.");
};
};
}
}

Categories

Resources