I am trying to create a stop button in my webapp. The webapp creates bulk shortcuts to different files. I have tried using $.connection.shortcutHub.stop() however this comes up with an error saying Cannot read property 'shortcutHub' of undefined(anonymous function)
The code is below. I need the connection to be stopped once the stop button has been clicked. The stop button's id is stopButton.
$(document).ready(function () {
// initialize the connection to the server
var progressNotifier = $.connection.shortcutHub;
// client-side sendMessage function that will be called from the server-side
progressNotifier.client.sendMessage = function (message, percent) {
// update progress
UpdateMessage(message, percent);
};
progressNotifier.client.redo = function () {
redo();
};
progressNotifier.client.success = function () {
success();
};
progressNotifier.client.fail = function () {
fail();
};
// establish the connection to the server and start server-side operation
$.connection.hub.start().done(function () {
$('#confirmbutton').click(function () {
jQuery.noConflict();
document.getElementById('closeButton').setAttribute("class", "btn btn-default hidden");
$('#myModal').modal('show');
//document.getElementById('confirmbutton').disabled = true;
//document.getElementById('barcodepanel').setAttribute("class", "panel panel-default");
var ticket = getCookie('ticket');
var path = getCookie('CBSShortcut_Path');
var checkeddocs = getCheckedBoxes("dcheck");
var checkedfolders = getCheckedBoxes("fcheck");
progressNotifier.server.createshortcuts(ticket, path, checkeddocs, checkedfolders);
});
$('#stopButton').click(function () {
document.getElementById('closeButton').setAttribute("class", "btn btn-default");
document.getElementById('confirmbutton').disabled = false;
//What do I put here?
});
});
function UpdateMessage(message, percent) {
// get result div
var msg = $("#result");
// set message
msg.html(message);
//set value of progress bar
document.getElementById('closeButton').setAttribute("class", "btn btn-default hidden")
$('#progressbar').css('width', percent + '%').attr('aria-valuenow', percent);
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1);
if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
}
return "";
}
function redo() {
document.getElementById('confirmbutton').disabled = false;
jQuery.noConflict();
$('#myModal').modal('hide');
}
// Pass the checkbox name to the function
function getCheckedBoxes(chkboxclass) {
var checkboxes = document.getElementsByClassName(chkboxclass);
var checkboxesChecked = [];
var ids = "";
// loop over them all
for (var i = 0; i < checkboxes.length; i++) {
// And stick the checked ones onto an array...
if (checkboxes[i].checked) {
checkboxesChecked.push(checkboxes[i]);
ids = ids + checkboxes[i].getAttribute("Name") + ",";
}
}
// Return the array if it is non-empty, or null
//return checkboxesChecked.length > 0 ? checkboxesChecked : null;
return ids;
}
}
);`
Any help is appreciated. I have tried everything that google has thrown my way (which has been mostly stackoverflow sites) and I am still having the same problem.
Have you tried:
$.connection.hub.stop().done(function() {
alert('stopped');
});
it will work.
You want to use the global SignalR Hub client connection because hubs share a single connection (aka don't use progressNotifier to do anything with the connection, only to listen for and send events.)
Your code to test this could look like:
$('#stopButton').click(function () {
document.getElementById('closeButton').setAttribute("class", "btn btn-default");
document.getElementById('confirmbutton').disabled = false;
$.connection.hub.stop();
//try to send a server event. Will throw an error
//Uncaught Error: SignalR: Connection must be started before data can be sent. Call .start() before .send()
});
This is a working code that I am using:
let connection;
let connectionUrl = 'https://someurl/hubEndpoint';
connection = new signalR.HubConnectionBuilder()
.withUrl(connectionUrl)
.build();
connection.serverTimeoutInMilliseconds = 60 * 10000;
connection.on("ReceiveMessage", (message) => {
console.log(message);
// to do appropriate coding
});
connection.start().then(function () {
console.log('Connected to server');
subject = new signalR.Subject();
});
setTimeout(() => {
connection.stop().then(function() {
console.log('Closed');
connection = null;
});
}, (2000));
Related
I have a custom extended property attached to the window object in JavaScript as follows:
Community.js
(function (window, document, $) {
'use strict';
var containerScrollPositionOnHideList = [];
var scrollToTopOnShowContainerList = [];
var userProfileInfo = {};
window.Community = $.extend({
//init
init: function () {
var Site = window.Site;
Site.run();
this.enableHideShowEventTrigger();
},
setUserInfo: function (userObj) {
if (UtilModule.allowDebug) { debugger; }
window.localStorage.setItem('userInfo', JSON.stringify(userObj));
var d = new $.Deferred();
$.when(this.initUserProfile(userObj.UserId)).done(function () {
d.resolve("ok");
});
},
getUserInfo: function () {
var userJson = window.localStorage.getItem('userInfo');
var userObj = JSON.parse(userJson);
return userObj;
},
})(window, document, jQuery);
The problem is that this extension property window.Community is null in certian scenarios when i refresh the page which i am going to describe below along with flow of code.
and here is a module in JavaScript to force reload scripts even if they are cached every time the page is refreshed as my code heavily depends on javascript calls so I just enabled it to make sure while I am still writing the code page reloads every time, the code is below as follows:
Util.js
var UtilModule = (function () {
var allowDebug = false;
var currentVersion = 0;
var properlyLoadScript = function (scriptPath, callBackAfterLoadScript) {
//get the number of `<script>` elements that have the correct `src` attribute
//debugger;
var d = $.Deferred();
$('script').each(function () {
console.log($(this).attr('src'));
});
if (typeof window.Community == 'undefined') {
//debugger;
console.log('community was undefined till this point');
//the flag was not found, so the code has not run
$.when(forceReloadScript(scriptPath)).done(function () {
callBackAfterLoadScript();
d.resolve("ok");
});
}
else {
console.log('Community loaded already and running now : ' + scriptPath);
callBackAfterLoadScript();
}
return d.promise();
};
var forceReloadScript = function (scriptPath) {
if (UtilModule.allowDebug) { debugger; }
var d = $.Deferred();
initCurrentVersion();
var JSLink = scriptPath + "?version=" + currentVersion;
var JSElement = document.createElement('script');
JSElement.src = JSLink;
JSElement.onload = customCallBack;
document.getElementsByTagName('head')[0].appendChild(JSElement);
function customCallBack() {
d.resolve("ok");
}
return d.promise();
};
var enableDebugger = function () {
allowDebug = true;
};
var disableDebugger = function () {
allowDebug = false;
};
var debugBreakPoint = function () {
if (allowDebug) {
}
};
var initCurrentVersion = function () {
if (currentVersion == 0) {
var dt = new Date();
var ttime = dt.getTime();
currentVersion = ttime;
}
};
var getCurrentVersion = function () {
return currentVersion;
};
return {
forceReloadScript,
properlyLoadScript,
enableDebugger,
disableDebugger,
debugBreakPoint,
allowDebug,
getCurrentVersion
};
})();
Note: I have made deferred objects to resolve only when the JSElement.onload has been called successfully. This step was taken just for testing purpose to make sure that I am not missing something before reaching a point to call the method where I am getting an error.
After that the code where I load scripts using UtilModule in my layout file look like as below:
_Layout.cshtml
<script src = "~/Scripts/Application/Modules/Util.js" ></script>
<script>
$.when(
UtilModule.properlyLoadScript('/Scripts/Application/Community.js', () => {
// Community.init() was supposed to be called here but i was still getting the error so i implemented this using promise that is returned from properlyLoadScript and call Community.init() further in .done callback to make sure that script is properly loading till this point.
//window.Community.init();
})
).done(function() {
window.Community.init();
});
</script>
#RenderSection("scripts", required: false)
Now coming to my main file where My index file is executing having (_layout.chsmtl) as parent layout
is
Index.cshtml
#{
ViewBag.Title = "My Blog";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<article id="BlogPage" style="margin: 5px;">
</article>
#section scripts{
<script type="text/javascript">
$(document).ready(function () {
$.when(UtilModule.properlyLoadScript('/Scripts/Application/Modules/Blog.js', () => {
})).done(function () {
BlogModule.init();
});
});
//});
</script>
}
from what I know is that #section scripts is executed only once all the scripts in the layout page are loaded first so seems like a safe place to initialize the code which is dependent on some script in _Layout.HTML file and further enclosed with $(document).ready() for testing just to make sure that this script loads after everything else is loaded already.
Note: I am running all this code in in-cognito mode in chrome so nothing is cached while this code is running
now my Blog.js file looks like as below
var BlogModule = (function () {
var moduleReference = this;
var PageId = "#BlogPage ";
var currentUser;
var BlogPostList = [];
var blogPostInfo = {};
//init
var init = function () {
if (UtilModule.allowDebug) { debugger; }
//This is where the problem happens
console.log(window.Community);
console.log(window.Community.getUserInfo());
currentUser = window.Community.getUserInfo();
initBlogInformation();
//window.Community.registerModule(BlogModule);
if (Object.keys(window.Community.getUserProfileObject()) <= 0) {
$.when(window.Community.initUserProfile(currentUser.UserId)).then(function () {
$.when(initBlogInformation()).done(function () {
//debugger;
console.log(BlogPostList);
window.WidgetManager.populateWidget(PageId, moduleReference);
loadBlogPostWidget();
loadBlogViewWidget();
loadBlogCommentsWidget();
});
});
}
else {
$.when(initBlogInformation()).done(function () {
window.WidgetManager.populateWidget(PageId, moduleReference);
loadBlogPostWidget();
loadBlogViewWidget();
loadBlogCommentsWidget();
});
}
};
var loadBlogIndexMenuWidget = function () {
if (UtilModule.allowDebug) { debugger; }
};
var loadBlogPostWidget = function () {
var widgetOptions = {};
widgetOptions.type = "BlogPostWidget";
widgetOptions.container = PageId + "#BlogPostWidgetContainer";
var settings = {};
settings.UserId = 1;
widgetOptions.settings = settings;
window.WidgetManager.loadWidget(widgetOptions);
}
var loadBlogViewWidget = function () {
var widgetOptions = {};
widgetOptions.type = "BlogViewWidget";
widgetOptions.container = PageId + "#BlogViewWidgetContainer";
var settings = {};
settings.UserId = 1;
widgetOptions.settings = settings;
window.WidgetManager.loadWidget(widgetOptions);
};
var loadBlogCommentsWidget = function () {
var widgetOptions = {};
widgetOptions.type = "BlogCommentsWidget";
widgetOptions.container = PageId + "#BlogCommentsWidgetContainer";
var settings = {};
settings.UserId = 1;
widgetOptions.settings = settings;
window.WidgetManager.loadWidget(widgetOptions);
};
var initBlogList = function () {
$.when(getBlogPosts()).then(function (results) {
if (UtilModule.allowDebug) { debugger; }
BlogPostList = results.Record;
console.log(BlogPostList);
});
};
var getBlogPosts = function () {
if (UtilModule.allowDebug) { debugger; }
var d = new $.Deferred();
var uri = '/Blog/GetBlogPosts?userId=' + currentUser.UserId;
$.post(uri).done(function (returnData) {
if (UtilModule.allowDebug) { debugger; }
if (returnData.Status == "OK") {
BlogPostList = returnData.Record;
BlogPostList.map(x => {
if (UtilModule.allowDebug) { debugger; }
x.UserName = window.Community.getUserProfileObject().UserName;
if (x.Comments != null) {
x.CommentsObject = JSON.parse(x.Comments);
x.CommentsCount = x.CommentsObject.length;
}
});
console.log(returnData.Record);
d.resolve("ok");
} else {
window.Community.showNotification("Error", returnData.Record, "error");
d.resolve("error");
}
});
return d.promise();
};
var initBlogInformation = function () {
//debugger;
var d = $.Deferred();
getBlogPosts().then(getBlogModelTemplate()).then(function () {
d.resolve("ok");
});
return d.promise();
};
//Get Blog Model
var getBlogModelTemplate = function () {
var d = new $.Deferred();
var uri = '/Blog/GetBlogModel';
$.post(uri).done(function (returnData) {
blogPostInfo = returnData.Record;
d.resolve("ok");
});
return d.promise();
};
return {
init: init,
};
})();
The error I have highlighted below
so the problem is in init function of BlogModule which is BlogModule.init() the page is idle for too long and I reload it I get the following error:
cannot call
window.Community.getUserInfo() of undefined implying that community is undefied
after couple of refreshes its fine and the issue doesn't happen unless I change reasonable portion of code for js files to be recompiled again by browser or the browser is idle for too long and I am not able to understand what is triggering this issue.
below is log from console
p.s. error occurs more repeatedly if i refresh page with f5 but happens rarely if i refresh page with ctrl + f5
Please any help would be of great value
Answering my own question, took a while to figure it out but it was a small mistake on my end just fixing the following function in Util.js fixed it for me
var properlyLoadScript = function(scriptPath, callBackAfterLoadScript) {
//get the number of `<script>` elements that have the correct `src` attribute
//debugger;
var d = $.Deferred();
$('script').each(function() {
console.log($(this).attr('src'));
});
if (typeof window.Community == 'undefined') {
//debugger;
console.log('community was undefined till this point');
//the flag was not found, so the code has not run
$.when(forceReloadScript('/Scripts/Application/Community.js')).done(function() {
//debugger;
$.when(forceReloadScript(scriptPath)).done(function() {
callBackAfterLoadScript();
});
d.resolve("ok");
});
} else {
console.log('Community loaded already and running now : ' + scriptPath);
$.when(forceReloadScript(scriptPath)).done(function() {
callBackAfterLoadScript();
});
}
return d.promise();
};
Is there any method in javascript that would behave like setInterval() and would stop when user leave the tab and resume when user enter the tab again?
You can create your own API, using Visibility API to detect when the tab becomes visible or hidden, and calling native setInterval and clearInterval under the hood.
var mySetInterval, myClearInterval;
(function() {
var data = Object.create(null),
id = 0;
mySetInterval = function mySetInterval(func, time) {
data[id] = {
nativeID: setInterval(func, time),
func: func,
time: time
};
return id++;
};
myClearInterval = function myClearInterval(id) {
if(data[id]) {
clearInterval(data[id].nativeID);
delete data[id];
}
};
document.addEventListener('visibilitychange', function() {
if(document.visibilityState == 'visible')
for(var id in data)
data[id].nativeID = setInterval(data[id].func, data[id].time);
else
for(var id in data)
clearInterval(data[id].nativeID);
});
})();
var mySetInterval, myClearInterval;
(function() {
var data = Object.create(null),
id = 0;
mySetInterval = function mySetInterval(func, time) {
data[id] = {
nativeID: setInterval(func, time),
func: func,
time: time
};
return id++;
};
myClearInterval = function myClearInterval(id) {
if(data[id]) {
clearInterval(data[id].nativeID);
delete data[id];
}
};
document.addEventListener('visibilitychange', function() {
if(document.visibilityState == 'visible')
for(var id in data)
data[id].nativeID = setInterval(data[id].func, data[id].time);
else
for(var id in data)
clearInterval(data[id].nativeID);
});
})();
var log = document.getElementById('log'),
timer;
document.getElementById('start').onclick = function() {
var num = 0;
myClearInterval(timer);
timer = mySetInterval(function(){
log.innerHTML = num++;
}, 1e3);
};
<input id="start" type="button" value="Start" />
<span id="log"></span>
Note the API above should not be mixed with the native one, e.g. do not attempt to create with mySetInterval and clear with clearInterval. Therefore, the IDs returned by mySetInterval are deliberately different than the native ones.
i have call the below function in my application
function workerCall() {
debugger;
if (typeof (Worker) !== "undefined") {
var worker = new Worker("Scripts/worker.js");
worker.onmessage = workerResultReceiver;
worker.onerror = workerErrorReceiver;
worker.postMessage({ 'username': Username });
function workerResultReceiver(e) {
$('.NotificationCount').html(e.data);
if (parseInt(e.data) != 0 && currentPage == "Alert") {
StateFlag = false;
$('.Notification').show();
$('.Drildown').each(function () {
var temp = this.id;
if ($('#' + temp).attr('expand') == "true") {
currentTab = temp;
StateFlag = true;
}
});
currentScrollPosition = $('body').scrollTop();
GetAlerts();
} else {
$('.Notification').hide();
}
}
function workerErrorReceiver(e) {
console.log("there was a problem with the WebWorker within " + e);
}
}
else {
}
}
the method will execute in IE,Chrome but when comes to Mozilla i got an error ReferenceError: workerResultReceiver is not defined.How can i resolve this error?
This happens because you are making reference to function that is not created yet. You need to put this:
worker.onmessage = workerResultReceiver;
worker.onerror = workerErrorReceiver;
Above
function workerErrorReceiver
line or at the end of the scope.
I have websocket service that works great when page is loaded. However, if connection is lost, and the service is trying to reconnect I am getting an error: "Uncaught ReferenceError: Service is not defined". Once I manually refresh page, service is working again. How can I reconnect without page refreshing? The app must reestablish that connection without any user involvement. This is my first angular app, so I am still in the process of learning the framework. Thank you.
angular.module('proApp').factory('webSocketService',
['$q', '$rootScope', function($q, $rootScope) {
var timeout = 2000;
var clearTimer = -1;
var port = '8081';
var server = '127.0.0.1';
var socket;
var host;
var Service = {};
function getSocketState() {
return (socket != null) ? socket.readyState : 0;
}
function onMessage(e) {
//console.log(e.data);
Service.message = JSON.parse(e.data);
$rootScope.$apply(function() {
Service.send();
});
}
//allows data to be used in controller
Service.send = function() {
$rootScope.$broadcast('broadcast');
};
function onError() {
clearInterval(clearTimer);
socket.onclose = function() {
};
clearTimer = setInterval("Service.getData()", timeout);
}
function onClose() {
clearInterval(clearTimer);
clearTimer = setInterval("Service.getData()", timeout);
}
function onOpen() {
clearInterval(clearTimer);
console.log("open" + getSocketState());
}
Service.getData = function() {
if ("WebSocket" in window) {
if (getSocketState() === 1) {
socket.onopen = onOpen;
clearInterval(clearTimer);
console.log(getSocketState());
} else {
try {
host = "ws://" + server + ":" + port + '';
socket = new WebSocket(host);
socket.onopen = onOpen;
socket.onmessage = function(e) {
onMessage(e);
};
socket.onerror = onError;
socket.onclose = onClose;
} catch (exeption) {
console.log(exeption);
}
}
}
};
// Public API here
return Service;
}]);
You have to change the use of setInterval to be like this:
clearTimer = setInterval(function () {
Service.getData();
}, timeout);
or just this:
clearTimer = setInterval(Service.getData, timeout);
This is the code I use, it can:
reconnect if connection is lost.
queue items while disconnected and send them on re-connection.
regular subscribing using the "listen" method.
"listenOnce" for an event once with a promise, after that the subscription is removed. Ideal for request/response using a correlationId
$rootScope.websocketAvailable indicates when the connection is available.
$rootScope.queuedMessages indicates when there are pending messages to be sent.
It is still part of a project in development, but I guess you can get the idea:
.service('$connection', ["$q", "$timeout", "websocketUrl", "$rootScope", function ($q, $timeout, websocketUrl, $rootScope) {
var connection = function () {
var me = {};
var listeners = [];
var oneListeners = [];
me.isConnected = false;
oneListeners.removeOne = function (listener) {
var index = oneListeners.indexOf(listener);
if(index!=-1)
oneListeners.splice(index, 1);
};
var correlationId = 0;
me.nextCorrelationId = function () {
return correlationId++;
};
$rootScope.queuedMessages = [];
me.listen = function (predicate, handler) {
listeners.push({ p: predicate, h: handler });
};
me.listenOnce = function (predicate, timeout) {
var deferred = $q.defer();
deferred.done = false;
var listener = { d: deferred, p: predicate };
oneListeners.push(listener);
if (timeout) {
$timeout(function () {
if (!deferred.done)
deferred.reject('timeout');
oneListeners.removeOne(listener);
}, timeout);
}
var promise = deferred.promise;
promise.then(function (data) {
deferred.done = true;
});
return promise;
};
var onopen = function () {
console.log('onopen');
$rootScope.websocketAvailable = true;
me.isConnected = true;
$rootScope.$$phase || $rootScope.$apply();
if ($rootScope.queuedMessages) {
for (var i = 0; i < $rootScope.queuedMessages.length; i++) {
ws.send(JSON.stringify($rootScope.queuedMessages[i]));
}
$rootScope.queuedMessages = null;
$rootScope.$$phase || $rootScope.$apply();
}
};
var onclose = function () {
console.log('onclose');
me.isConnected = false;
$rootScope.websocketAvailable = false;
$rootScope.$$phase || $rootScope.$apply();
$rootScope.queuedMessages = $rootScope.queuedMessages || [];
setTimeout(function () {
ws = connect();
}, 5000);
};
var onmessage = function (msg) {
console.log('onmessage');
var obj = JSON.parse(msg.data);
for (var i = 0; i < listeners.length; i++) {
var listener = listeners[i];
if (listener.p(obj))
listener.h(obj);
}
var remove = [];
for (var i = 0; i < oneListeners.length; i++) {
var listener = oneListeners[i];
if (listener.p(obj)) {
var o = obj;
listener.d.resolve(o);
remove.push(listener);
}
}
for (var i = 0; i < remove.length; i++) {
oneListeners.removeOne(remove[i]);
}
};
var onerror = function () {
console.log('onerror');
};
me.send = function (obj) {
if ($rootScope.queuedMessages)
$rootScope.queuedMessages.push(obj);
else
ws.send(JSON.stringify(obj));
}
var setHandlers = function (w) {
w.onopen = onopen;
w.onclose = onclose;
w.onmessage = onmessage;
w.onerror = onerror;
};
var connect = function () {
console.log('connecting...');
var w = new WebSocket(websocketUrl);
setHandlers(w);
return w;
}
var ws = connect();
return me;
};
return connection();
}])
I am new to doing jQuery ajax calls and am trying to test an ajax call I have attempted to write today. Here it is.
var heartbeatInterval = 30000;
var heartBeatTimer = null;
var retryCount = 0;
var maxRetries = 10;
$().ready(function () {
var url = $.url("/pollBulletin.htm");
heartBeatTimer = setInterval(function () {
$.ajax({
url: url,
type: 'GET',
error: function (data) {
retryCount = retryCount + 1;
if (heartBeatTimer != null && retryCount >= maxRetries) {
clearInterval(heartBeatTimer);
}
},
success: function (bulletinBarMessage) {
retryCount = 0;
var respContent = "";
respContent += bulletinBarMessage.messageLevel + " : ";
respContent += bulletinBarMessage.message;
}
});
// When communication with the server is lost stop the heartbeat.
}, heartbeatInterval);
});
At the moment the code is never falling into the success part of the call. Can someone confirm if it looks ok? I'm not sure if I have coded this right. I know the server side code is doing the write thing. At the moment it is just return a null (server side).
Server side...
public BulletinBarMessage getBulletinBarMessage() {
JdbcTemplate select = this.getJdbcTemplate();
List<BulletinBarMessage> messages = select.query(BULLETIN_LOOKUP_SQL, new BulletinBarMessageRowMapper());
BulletinBarMessage bulletinBarMessage = null;
if (messages != null && !messages.isEmpty()){
bulletinBarMessage = (BulletinBarMessage)messages.get(0);
}
return bulletinBarMessage;
}