How to access the invocationId in SignalR core? - javascript

I'm creating an app with SignalR Core on Azure. Now I need to match the invoked request with the returned value and callback. I would like to use the invocationId to make sure the method that will be executed is the latest invoked request. To avoid as happens in the attached image.
var _this.latestInvokeId = ??
connection.invoke('getData', _this.ID)
.then(function (data) {
if(this.invocationId === _this.latestInvokeId)
console.log('Use the data', data)
})
.catch(function (error) {
console.log(error);
});
When the getData is invoked multiple times in a short interval I would like to be sure to use the right response. So the response with invocationId 8 needs to be ignored and only the response with invocationId 9 is used.

I've implemented a new id that is send on the request and can be validated when the value is returned.

Related

Send data to EJS after calling initial res.render?

I'm trying to pass a variable to EJS a second time in my code and am running into trouble. Here is my code:
axios.get(yearURL)
.then(function (res) {
let data = res.data.MRData.SeasonTable.Seasons;
years = data.map(d => d.season);
app.get('/', function (req, res) {
res.render('index.ejs', {
years: years
});
app.post('/down', function(req, res) {
let year = req.body;
res.redirect('/');
axios.get(`http://ergast.com/api/f1/${year.year}/drivers.json`)
.then(function (res) {
let data = res.data.MRData.DriverTable.Drivers;
drivers = data.map(d => `${d.givenName} ${d.familyName}`);
})
.catch(function (err) {
console.log(err);
})
res.render('index.ejs', {
drivers: drivers,
years: years
});
Whenever I run this however, I receive an error that I cannot set headers after they are sent to the client. I've also read elsewhere that apparently you can not call res.render twice. So my question is, how can I pass another set of data to EJS after I have already called res.render once before?
Here it is as pseudocode. It's good to start your program with this level of logical structure, and then implement it:
Define ready = false, errored = false, and data = undefined
variables.
Get the data from the remote API, in the then branch, set
ready = true, assign result to data. In the error branch, set errored
= true. Should we retry on error?
Define the / GET route.
If not ready, check errored. If not errored, we are still waiting for the data. In this case, do we wait for the call to resolve, or return something to the client to let them know?
If not ready, and errored, tell the client that there was an error.
If ready == true, then we have data to render a response to the client.
Define the /down route. It needs to take a year parameter, and we need to make an async call in the route handler to get the data.
Can we cache the data, so that subsequent calls for the same year return data that we fetched previously? If we can, use an object as a lookup dictionary. If the object has a key for that year, use the cached data to render the response. If not, make the call, and in the then branch, add the response to the cache object, and use the data to render the response.

Should I use response.send() in 'finally' block when writing Google Cloud Functions?

Im' trying to understand using promises with Google Cloud Functions a bit better. I just learned about the 'finally' method on promises, which is called after all promises in the chain are fully resolved or rejected. In a http function is it good practice to put response.send() inside of the finally method?
The below code uses request-promise-native for the http request. In the first .then() I call parseSchedule, which uses the cheerio web scraping api to loop through some data and on a website, and add it to the scheduledGames array (synchronously, I think).
I return from that and the then log that data to the console in writeDB, but one thing I noticed is that I see response.send() log 'execution finished' before I see the data from scheduleGames in the log. Is that correct?
Should I be using the 'finally' block like this?
Thanks,
const options = {
uri: 'https://www.cbssports.com/nba/schedule/' + urlDate,
Connection: 'keep-alive',
transform: function (body) {
return cheerio.load(body);
}
};
return request(options)
.then(parseSchedule)
.then(writeSchedule)
.catch((err) => console.log("there was an error: " + err))
.finally(res.send("execution finished"));
function parseSchedule($){
const scheduledGames = [];
$('tbody').children('tr').each((i, element) => {
const gameTime = $(element).children('td').eq(2).find('a').text()
const scheduledGame = { gameTime: gameTime};
scheduledGames.push(scheduledGame);
});
return scheduledGames;
}
function writeDB(scheduledGames){
console.log(scheduledGames);
}
}
It typically makes more sense to send a success response at the time in the promise chain when everything is successful, or send an error response in a catch handler. If you do these two things, it doesn't make sense to use finally at all, since success and error are the only two cases you really need to handle. Unless you have some special case, stick to just success and error.

Cron http request to cloud function - look into database

I'm trying to use cron to trigger my cloud function in order to look at my database every couple hours. I can trigger the function automatically, but the output is not what I was expecting. I'm just a tad bit confused on why I am not able to retrieve anything from the database, meaning I can't log out my console.log("refund"). I currently have 1 document in the request collection and has 1 file with the replied field that satisfies replied == false. So I'm just confused on how to go about this correctly since I believe it should've logged that once?
exports.daily_job = functions.https.onRequest((req, res) => {
const key = req.query.key;
// Exit if the keys don't match.
if (!secureCompare(key, functions.config().cron.key)) {
console.log('The key provided in the request does not match the key set in the environment. Check that', key,
'matches the cron.key attribute in `firebase env:get`');
res.status(403).send('Security key does not match. Make sure your "key" URL query parameter matches the ' +
'cron.key environment variable.');
return null;
}
let db = admin.firestore()
let request = db.collection('request')
.where('replied', '==', false)
.get().then(function(querySnapshot){
querySnapshot.forEach(function(doc) {
console.log("refunded")
})
})
.catch(function (error) {
console.log('Error getting documents: ', error)
res.send('error');
})
res.send('finished refund');
return null;
});
You're not waiting on the promise returned by get(), which is asynchronous. As your code is now, the entire function sends a response "finished refund" immediately after the query is made, before it has time to finish. Once you send a response, the function is terminated.
You need to send the client response only after all the async work is complete in your function, which would be in BOTH your then() and catch() callbacks.

Need clarification on calling Meteor methods asynchronously

So i've been doing some reading and I think I have a general grasp on this subject but could use some insight from someone more experienced. I've been trying to write a simple RSS reader in Meteor and have been facing some issues with calling the Meteor method asynchronously. I currently define the method on the server(synchronously) and call it on the client(asynchronously). What I don't understand is that when I try to make the HTTP.call on the server, I return an undefined value passed to my client if I pass a callback into the request. But when I make the API request synchronously everything seems to work fine. Is this the normal behavior I should expect/the way I should be making the API call?
Meteor.methods({
getSubReddit(subreddit) {
this.unblock();
const url = 'http://www.reddit.com/r/' + subreddit + '/.rss';
const response = HTTP.get(url, {}, (err, res) => {
if(!err) {
//console.log(res.content);
return res;
} else {
return err;
}
});
}
});
Here's the method defined on the server side. Note that logging res.content shows that I'm actually getting the right content back from the call. I've tried reading some other answers on the topic and seen some things about using Future/wrapAsync, but I'm not sure I get it. Any help would be greatly appreciated!
The HTTP.get is doing async work, so callback passed to it will be called out of this meteor method call context.
To get desired result you should do it like this:
Meteor.methods({
getSubReddit(subreddit) {
// IMPORTANT: unblock methods call queue
this.unblock();
const url = 'http://www.reddit.com/r/' + subreddit + '/.rss';
const httpGetSync = Meteor.wrapAsync(HTTP.get);
try {
const response = httpGetSync(url, {});
//console.log(response.content);
return response.content;
} catch (err) {
// pass error to client
throw new Meteor.Error(...);
}
}
});

Angular 2 Http get not triggering

As said in the title, nothing is happening when I subscribe to my observable. There is no error in the console or during the build. Here is my code :
My service
getBlueCollars(): Observable<BlueCollar[]> {
return this.http.get(this.defaultAPIURL + 'bluecollar?limit=25').map(
(res: Response) => {
return res.json();
});
}
My component
ngOnInit() {
this.planifRequestService.getBlueCollars().subscribe(
data => {
this.blueCollars = data;
console.log('Inner Blue Collars', this.blueCollars);
},
err => console.log(err)
);
console.log('Value BlueCollars : ', this.blueCollars);
}
So the second console.log is triggering with "Value BlueCollars : Undefined", and the log in my subscribe is never showed. As well, I can't see the request sent in the Networt tab of Chrome.
So I tried to simplify everything with the following code :
let response: any;
this.http.get('myUrl').subscribe(data => response = data);
console.log('TestRep: ', response);
Same problem here, no error, response is undefined. It seems the subscribe is not triggering the observable. (The URL is correct, it is working on my swagger or with postman.)
I'm on Angular 2.4.9
Edit
So I tried to copy/past the code of my request on a brand new project, everything is working fine. The request is triggered and I can get the JSON response correctly. So there is something maybe on the configuration of my project that is forbiding the request to trigger correctly.
Ok just found what was going on. I am using a fake backend in order to try my login connexions that is supposed to catch only specified URL. However for wathever raison it was catching all the requests, so that explain everything. Thx for your help everybody.
Try adding a catch block to your service code:
getBlueCollars(): Observable<BlueCollar[]> {
return this.http.get(this.defaultAPIURL + 'bluecollar?limit=25')
.map(
(res: Response) => {
return res.json();
})
.catch(err => Observable.throw(err))
}
Don't forget to
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';`
I imagine this will result in the error that'll give you an idea where your code is going wrong.
The reason the console.log outside the subscribe call is undefined is because the subscribe/http call is happening asynchronously and so, in effect, the order (in time!) the code is running is:
1) the observable is subscribed to (and then waits for a response)
2) the outer console log runs with blueCollars undefined
3) when the response (or error) comes back from the http request (potentially after several seconds), only then will the inner assignment of this.blueCollar = data happen (and the inner console log), OR an error will get logged
Apart from that the subscribe code looks fine...!

Categories

Resources