SignalR connection.on & connection.invoke - asp.net-mvc

I have the following code
var connection = new signalR
.HubConnectionBuilder()
.withUrl("/bidHub")
.build();
connection.start().then(res => {
connection.invoke("JoinGroup", auctionId)
.catch(err => console.log(err));
}).catch (function (err) {
return console.error(err.toString());
});
ajax call here
connection.on("RefreshBids", function (currentBid, lastBidder) {
document.getElementById("currentPrice").textContent = `$${currentBid}`;
document.getElementById("lastBidder").textContent = `${lastBidder}`;
});
connection.invoke("RefreshBids", JSON.stringify(currentBid), JSON.stringify(lastBidder)).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
The code works with both 'connection.on' and with 'connection.on' + 'connection.invoke', but when they are both, 'connection.invoke' gives the error that it does not find 'currentBid' and 'lastBidder', it still works. It seems to work with 'connection.on', but should I use 'connection.invoke' as well

Usage depends on if you are using a generated proxy. Generally you will use one or the other but not both. See generated proxy doc and calling server methods doc for more details.

Related

Migrate Google Workbox setDefaultHandler // setCatchHandler from v2 to v3

I'm trying to migrate my old code from google workbox v2 to workbox v3, and i can't use workbox.routing.registerNavigationRoute because my default route '/' (which is where my appshell is) is a runtime cache (because it's for a multilingual website https://www.autovisual.com with languages put in subfolder '/fr', '/es' ... with a unique Service-Worker scoped at '/').
This is the v2 code :
workboxSW.router.setDefaultHandler({
handler: ({
event
}) => {
return fetch(event.request);
}
});
workboxSW.router.setCatchHandler({
handler: ({
event
}) => {
if (event.request.mode === 'navigate') {
return caches.match('/');
}
return new Response();
}
});
It seems pretty basic : the goal is to catch all request 'navigate' that didn't match any other route and send the cached version, network first, of the url '/'.
For the info in the client js i use :
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
caches.open('rootCacheNetworkFirst').then(function(cache) {
cache.match('/').then(function(response) {
if (!response) {
cache.add('/');
}
});
});
navigator.serviceWorker.register('/sw.js', {
scope: "/"
});
});
}
I can't find any example with the new v3 workbox.routing.setDefaultHandler and workbox.routing.setCatchHandler and i'm stuck :(
I don't think that using either setDefaultHandler or setCatchHandler is relevant for that described use case.
To accomplish what you describe, add the following code to your service worker file after all other routes are registered. (In Workbox v3, the first-registered-route takes precedence.) You just need to configure a NavigationRoute and register it:
const networkFirst = workbox.strategies.networkFirst({
cacheName: 'your-cache-name',
});
const navigationRoute = new workbox.routing.NavigationRoute(networkFirst, {
// Set blacklist/whitelist if you need more control
// over which navigations are picked up.
blacklist: [],
whitelist: [],
});
workbox.router.registerRoute(navigationRoute);

Service Worker caching not recognizing timeout as a function

I was watching Steve Sanderson's NDC presentation on up-and-coming web features, and saw his caching example as a prime candidate for an application I am developing. I couldn't find the code, so I have typed it up off the Youtube video as well as I could.
Unfortunately it doesn't work in Chrome (which is also what he is using in the demo) It fails with Uncaught TypeError: fetch(...).then(...).timeout is not a function
at self.addEventListener.event.
I trawled through Steve's Github, and found no trace of this, nor could I find anything on the NDC Conference page
//inspiration:
// https://www.youtube.com/watch?v=MiLAE6HMr10
//self.importScripts('scripts/util.js');
console.log('Service Worker script running');
self.addEventListener('install', event => {
console.log('WORKER: installing');
const urlsToCache = ['/ServiceWorkerExperiment/', '/ServiceWorkerExperiment/scripts/page.js'];
caches.delete('mycache');
event.waitUntil(
caches.open('mycache')
.then(cache => cache.addAll(urlsToCache))
.then(_ => self.skipWaiting())
);
});
self.addEventListener('fetch', event => {
console.log(`WORKER: Intercepted request for ${event.request.url}`);
if (event.request.method !== 'GET') {
return;
}
event.respondWith(
fetch(event.request)
.then(networkResponse => {
console.log(`WORKER: Updating cached data for ${event.request.url}`);
var responseClone = networkResponse.clone();
caches.open('mycache').then(cache => cache.put(event.request, responseClone));
return networkResponse;
})
//if network fails or is too slow, return cached data
//reference for this code: https://youtu.be/MiLAE6HMr10?t=1003
.timeout(200)
.catch(_ => {
console.log(`WORKER: Serving ${event.request.url} from CACHE`);
return caches.match(event.request);
})
);
});
As far as I read the fetch() documentation, there is no timeout function, so my assumption is that the timeout function is added in the util.js which is never shown in the presentation... can anyone confirm this? and does anyone have an Idea about how this is implemented?
Future:
It's coming.
According to Jake Archibald's comment on whatwg/fetch the future syntax will be:
Using the abort syntax, you'll be able to do:
const controller = new AbortController();
const signal = controller.signal;
const fetchPromise = fetch(url, {signal});
// 5 second timeout:
const timeoutId = setTimeout(() => controller.abort(), 5000);
const response = await fetchPromise;
// …
If you only wanted to timeout the request, not the response, add:
clearTimeout(timeoutId);
// …
And from another comment:
Edge & Firefox are already implementing. Chrome will start shortly.
Now:
If you want to try the solution that works now, the most sensible way is to use this module.
It allows you to use syntax like:
return fetch('/path', {timeout: 500}).then(function() {
// successful fetch
}).catch(function(error) {
// network request failed / timeout
})

Falcor Router should return the value from external API

I am new to JavaScript frameworks and currently trying to setup a falcor router calling an external api (for now consider it as an express api app + mango db, hosted at 3000 port).
Now, I am able to use the request package (commented out lines) and successfully call the Express Api app (which returns obj.rating = 4). But I am unable to send this value from the falcor router instead of the hard-coded value "5".
Below is the falcor-router's server.js code:
app.use('/rating.json', falcorExpress.dataSourceRoute(function (req, res) {
return new Router([
{
route: "rating",
get: function() {
var obj;
// request('http://localhost:3000/rating/101', function (error, response, body) {
// obj = JSON.parse(body);
// console.log('rating:', obj.rating); // obj.rating = 4
// });
return {path:["rating"], value:"5"};
}
}
]);
}));
The below is the code for index.html:
<script>
function showRating() {
var model = new falcor.Model({source: new falcor.HttpDataSource('http://localhost/rating.json') });
model.
get("rating").
then(function(response) {
document.getElementById('filmRating').innerText = JSON.stringify(response.json,null, 4);
});
}
</script>
I also tried to look at the global variable declaration, synchronize http request calls, promises, then statements etc. But nothing seemed to work, clearly I am missing out something here - not sure what.
The router's get handler expects the return value to be a promise or an observable that resolves to a pathValue. To get your request against the db to work, simply return a promise that resolves to a pathValue, e.g.
return new Router([
{
route: "rating",
get: function() {
return request('http://localhost:3000/rating/101', function (error, response, body) {
return { path: ["rating", value: JSON.parse(body).rating };
});
}
}
]);

How to run http call as background in ionic Framework?

I am using ionic Framework. i have multiple HTTP service which is working fine. Now problem is that whenever i get response of any http call. i can't proceed further.
Can we run HTTP Service as a background process. So my application continues works without waiting for result.
here is my code
articleService.getArticles().then(function() {
},function(err){
});
and sercvice code
$http({
url: "http://myservice.com",
data: { user_id: 1 },
method: 'POST',
withCredentials: true,
}).success(function (data) {
deferred.resolve(data);
}).error(function (err) {
deferred.resolve(0);
})
return deferred.promise;
}
Any idea? I need a solution in ionic framework which will work both for ios and andriod?
Thanks
try to use html5 web workers what u need to do is multithreading and because that javascript is single threading environment you have to web workers
https://html.spec.whatwg.org/multipage/workers.html
Look at this plunker this what you need and it is all angularjs so will work with ionic.
var app = angular.module('angularjs-starter', []);
app.config(function($routeProvider) {
$routeProvider.
when('/', {controller:'StartCtrl', templateUrl:'start.html'}).
when('/main', {controller:'MainCtrl', templateUrl:'main.html'}).
otherwise({redirectTo:'/'});
});
app.controller('MainCtrl', function($scope, Poller) {
$scope.name = 'World';
$scope.data = Poller.data;
});
app.controller('StartCtrl',function(){});
app.run(function(Poller) {});
app.factory('Poller', function($http, $timeout) {
var data = { response: {}, calls: 0 };
var poller = function() {
$http.get('data.json').then(function(r) {
data.response = r.data;
data.calls++;
$timeout(poller, 1000);
});
};
poller();
return {
data: data
};
});
Maybe i misunderstand your question but i think your service code is wrong.
Try something like this
myApp.factory('articleService', function($http) {
return {
getArticles: function getArticles() {
return $http({...}); // $http returns a promise, so you dont need your own defer.promise
}
}
});
//usage
//first: send or get data async
articleService.getArticles().then(function(resp){
alert('called second');
...
});
// second: do something else, this will not wait for your response
alert('called first');

SignalR- send data to a specific client

I want to send data to a specific client. to do that I am trying with the following;
public Task GetWaitingOrdersCount(string id, string clientId)
{
DateTime today = Util.getCurrentDateTime();
var data = 10
return Clients.Client(Context.ConnectionId).loadOrders(data);
//return data;
}
In the above code, I want to send 'data' to the 'clientId' passed to this method.
BUT I m having an error in this line
return Clients.Client(Context.ConnectionId).loadOrders(data);
And the error is
'System.Threading.Tasks.Task<object>' does not contain a definition for 'loadOrders'
the client side code
con.loadOrders = function (data) {
loadOrders(data);
};
function loadOrders(data) {
$('#totalOrders').html(data);
}
Any help about the error???
EDIT:
This is my full client code..
<script type="text/javascript">
var con;
$(document).ready(function () {
con = $.connection.messagingHub;
$.connection.hub.start(function () {
var myClientId = $.connection.hub.id;
con.getWaitingOrdersCount('<%:ViewBag.rid%>',myClientId).done(function (data) {
console.log(data);
});
});
con.client.loadOrders = function (data) {
loadOrders(data);
};
});
function loadOrders(data) {
$('#totalOrders').html(data);
I just tried out your code (slightly modified) and it works fine for me. What version of SignalR are you using? Judging by your server code I'd say 1.0Alpha1+ but your client code looks more like 0.5.3, that is unless your con object is assigned to $.connection.yourhub.client;
If you update to SignalR 1.0Alpha2 and change your client code to be:
var con = $.connection.myCon;// This is arbitrary and would change based on your naming
con.client.loadOrders = function (data) {
loadOrders(data);
};
function loadOrders(data) {
$('#totalOrders').html(data);
}
That being said I believe your issue has to do with the version of SignalR you are using, server side that is: since you're receiving a task oriented error. Another piece of information that might be beneficial would be to know how GetWaitingOrdersCount is being called. Aka is it being invoked from the client directly via: con.server.getWaitingOrdersCount or is it being called from within the hub.
Hope this info helps!

Resources