trying to understand a code fragment of an article on socket.io and redis - redis

I'm trying to understand an article here, and now everything is clear but one code fragment, mentioned on pre-last code block, with a total of 1 to 17 lines, and this fragment is from line 1 to 9:
app.use(function(req,res,next) {
redis.get(req.user.email, function(err, id) {
if (err) next(err);
req.emitToUser = function() {
var soc = id && io.to(id);
soc.emit.apply(soc, arguments);
}
});
});
and I think its some shortcomings in my javascript knowledge are the root cause.
My knowledge over this code fragment:
The 'apply' method will execute the 'emit' with 'soc' as 'this' value
and feeds the 'emit' method with 'arguments' (am I right here
please?)
socket.id is related to the email of socket owner, because id.to(id) is based on the fact that the socket.id is the room where every socket is joined with itself. Redis provides the key-value data structure that holds user email as key, and the value is the socket.id.
problems:
where 'arguments' is coming from?
what's the purpose of this code fragment?
Please make me clear.

There are some issues with this code, but the general idea is to define a method on the req object req.emitToUser() for every incoming request that will allow some other route handler later in the chain to use that method to emit to the user who make the request. This is a common desire to want to connect a currently connected socket.io connection to the user making the http request.
Let's look at each line here:
redis.get(req.user.email, function(err, id) {
Look up the req.user.email in the redis database to get a socket.io id associated with that email that has previously been saved in that redis database.
if (err) next(err);
If it wasn't found in redis, make this request fail with an error.
req.emitToUser = function() {
Assign a new method to the current req object so that other route handlers later in the chain can use that method.
var soc = id && io.to(id);
Look up the id value in socket.io to get the socket for that id. Technically io.to() doesn't return the socket, but it returns an object that you can call emit() on that will send to that socket.
soc.emit.apply(soc, arguments);
The role of soc.emit.apply(soc, arguments); is this:
Execute the soc.emit() method
Set the this value when executing that method to the soc object.
Set the arguments when executing that method to whatever the arguments were that were passed to req.emitToUser(x, y, z) when it was called.
Here's a more concrete example:
function fn(a, b, c) {
console.log(a, b, c);
}
fn.apply(null, [1, 2, 3]);
Using fn.apply(null, [1, 2, 3]); will be the same as:
fn(1, 2, 3);
Now, you'd likely never use .apply() in this exact way when the arguments are already known. The case for using it is when you have some arbitrary array that is passed to you (you don't know what's in it) and you want to pass those arguments along to some other function in the exact same order as they were given to you. That's what soc.emit.apply(soc, arguments); is doing. It's taking the arguments object (which is an array-like structure that represents the arguments that were passed to the parent function req.emitToUser() and passing those exact arguments on it sock.emit(). If you knew exactly how many arguments there would be, then you could hard-code that same code as this:
app.use(function(req,res,next) {
redis.get(req.user.email, function(err, id) {
if (err) next(err);
req.emitToUser = function(msg, data) {
var soc = id && io.to(id);
soc.emit(msg, data);
}
});
});
But, .apply() creates a more generic solution that will work regardless of how many arguments were passed to req.emitToUser() as it will just pass all the arguments on to soc.emit().
This line of code is a bit suspect:
var soc = id && io.to(id);
It appears to be trying to protect against there not being a proper id returned from redis earlier. But, if there's no id, then soc will not be a valid object and the following like of code:
soc.emit.apply(soc, arguments);
will throw. So, the id && io.to(id) isn't really providing the proper protection. It appears this should more likely be:
app.use(function(req,res,next) {
redis.get(req.user.email, function(err, id) {
if (err) next(err);
req.emitToUser = function() {
if (id) {
var soc = io.to(id);
soc.emit.apply(soc, arguments);
} else {
// not sure what you want here, perhaps return an error
// or throw a more meaningful exception
}
}
});
});

Related

Can we overwrite 'expect' method of testcafe's TestController

I am looking for a way to overwrite expect method for TestController. My idea is existing tests whoever used t.expect method, I want to perform additional steps in those cases.
I came up with below sample code but testcafe runtime fails with below error
TypeError: Cannot read property '_expect$' of undefined
sample code attempting to override:
import { Selector } from "testcafe";
fixture`Getting Started`.page`http://devexpress.github.io/testcafe/example`;
test("My first test", async (t) => {
t = modify(t);
await t.typeText("#developer-name", "John Smith").click("#submit-button");
// Use the assertion to check if the actual header text is equal to the expected one
await t
.expect(Selector("#article-header").innerText)
.eql("Thank you, John Smith!");
});
function modify(t) {
let prevExpect = t.expect;
t.expect = (param) => {
console.log("modified expecte has been used");
return prevExpect(param);
};
return t;
}
Also, when using t.click(Selector(...).expect(...), It doesn't use my overwritten expect. How to make it work in the call chain as well?
Technically, it's possible to overwrite the expect method, but please note that this approach may lead to incorrect work and unexpected errors.
You need to modify your modify function as follows:
function modify (t) {
let prevExpect = t.expect;
t.expect = (param) => {
console.log("modified expect has been used");
return prevExpect.call(t, param);
};
return t;
}
As for the t.click(Selector(...).expect(...) issue, you call the expect method of Selector, but Selector does not have the expect method.
You need to add ) after Selector:
await t.click(Selector(...)).expect(...)

When does a strongloop promise execute the database call?

I was refactoring someone elses code.
let promiseObj = Application.models.Widget.findById(connection.childId)
if (connection.child != 'Widget') {
typeES = "media"
promiseObj = Application.models.Media.findById(connection.childId)
}
promiseObj.then((obj) => {
let ownerId = obj.ownerId
let promiseUser = Application.models.MyUser.findById(ownerId)
})
The question is, does the server get called when
"let promiseObj = Application.models.Widget.findById(connection.childId)" is declared.
Or does the server get called when the .then is declared as the promise have a way to be fulfilled.
This is loopback with ES6.
Thanks guys/girls :D
Does the server get called when let promiseObj = Application.models.Widget.findById(connection.childId) is declared.
Yes, the server request is made as soon as the findById method is called.
Or does the server get called when the .then is declared as the promise have a way to be fulfilled.
then is just a method that is called, there is no declaration here. And it doesn't "give the promise a way to be fulfilled" - the promise will always resolve when the request finishes (fulfill in case of success and reject in case of an error), regardless whether there are any callbacks or not.
If you install a callback via then, it will be called when the promise is fulfilled.
So yes, I'm pretty certain that you should refactor this code:
let promiseObj;
if (connection.child != 'Widget') {
promiseObj = Application.models.Widget.findById(connection.childId);
} else {
typeES = "media"
promiseObj = Application.models.Media.findById(connection.childId)
}
let promiseUser = promiseObj.then((obj) => {
return Application.models.MyUser.findById(obj.ownerId);
});
As Erazihel is explaining, the declaration does not fire the resolve, it is called when you call .then()
I made a simple example in order to visualize the effect, there you will check that the time of the resolve matches the time where you call .then(), not on declaration.
p1.then(
// Then calls the resolve so the execution time 'resolve' matches .then
function(val) {
var timeMeAgain = new Date().toLocaleString();
log.insertAdjacentHTML('beforeend', val.thisPromiseCount +
') Promise done, then is called here (<small>Async call finished, .then called at: '+timeMeAgain+', promise executed at": '+val.timeCalledAt+' </small>)<br/>');
})
Check the example code here
*Code is based in the MDN example. Check documentation here
EDIT
About the resolve method, as the MDN documentation explains:
The method returns a Promise object that is resolved with the given value.
If the value is a thenable (i.e. has a "then" method), the returned
promise will "follow" that thenable, adopting its eventual state;
otherwise the returned promise will be fulfilled with the value.
Meaning that the response object will be returned when the Database or endpoint returns the information, not on declaration of the promise.

Node-SQLite's db.each using large amount of memory for broad queries

I am attempting to run the below listed function in Node on a VM with 3.5GB of memory. The query I am running returns ~2.25 million rows. It fails due to what appears to be a memory leak - if someone has encountered this or has suggestions on how to handle the increasing memory problem on this call, I'd appreciate it.
var sqlite3 = require('sqlite3').verbose();
db.each(query, function (error, data) {
if (error) {
console.log('Failed.');
} else {
console.log('Current perf: ', process.memoryUsage());
}
error = null; data = null;
}, function (error, responseLength) {
console.log('done with all');
});
Each row looks like this:
2015-11-13T01:17:32Z|510|40.632087|-73.946855|315.47|2|20151112|9910715-SCPD5-SC_D5-Weekday-10-SDon|0|307840|73.51|5.53
The goal is to handle each row one at a time and write them to a CSV, line by line, via a stream. The thought was that, by doing this, I would avoid having to hold the entire query response in memory - but this goal seems to be thwarted given the current situation.
I think you need to use a prepared statement and setImmediate(), like this:
var sqlite3 = require('sqlite3').verbose();
var stmt = db.prepare(query);
doQuery();
function doQuery(){
stmt.get(function(error, data){
if(data){
if(error){
console.log(error);
} else {
// do something with data here.
}
setImmediate(function(){
doQuery();
});
}
});
}
Explanation:
1) Prepared statements makes the client retrieve each row separately, rather than trying to grab all the results at once. The data param will be undefined when it hits the last row.
2) setImmediate() makes sure that the callback loop isn't called recursively, which could blow your call stack if the number of rows is too high.

Scala 2 futures containing api calls race condition

I've defined some API calls in Futures that make API calls to Mashery and Stripe
val stripeFuture = Future { // api call }
val masheryFuture = Future { //api call }
For the stripeFuture -The main logic is to set the stripeCustomerId on a Client object within the onSuccess block
stripeFuture onSuccess {
//client.stripeCustomerId
}
I've wrapped up the API calls in a for-comprehension similar to the example in Futures and Promises
val apiCalls = for {
masheryInfo <- masheryFuture
stripeCustomer <- stripeFuture
}
There is a rollback if one of the API calls fail
apiCalls onFailure {
case pse: MasheryException => {
// delete stripe customer id
}
case e: StripeException => {
//delete mashery api key
}
The problem is when the call to Mashery fails 'masheryFuture', I want to rollback 'get the stripe id' from the Client object but there is a around a 1 second delay til that call finishes and it doesn't set the stripeCustomerId until it hits the onSuccess block so within the ase pse: MasheryException => { } block, client.getstripeCustomerId returns null.
Is there a way of getting around this race condition for both of the API calls
Use Future.andThen.
The doc:
Applies the side-effecting function to the result of this future, and
returns a new future with the result of this future.
This method allows one to enforce that the callbacks are executed in a
specified order.
for (f <- Future(x).andThen { y }) etc.
Update:
for (f <- Future(x) andThen {
case Success(x) => use(x)
case _ => // ignore
}) yield result

CameraCaptureUI.captureFileAsync fails to return IAsyncOperation object

For some reason, my code is unable to retrieve the IAsyncOperation object that is returned upon calling captureFileAsync method of the Windows.Media.Capture.CameraCaptureUI() method. The IAsyncOperation object is returned according to this documentation. In that documentation link, it states:
Return value
Type: IAsyncOperation<StorageFile>
When this operationcompletes, a StorageFile object is returned.
So here is my code:
var dialog = new Windows.Media.Capture.CameraCaptureUI();
var aspectRatio = { width: 4, height: 3 };
dialog.photoSettings.croppedAspectRatio = aspectRatio;
appSession.InAsyncMode = dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo).done(function (file) {
if (file) {
self.addPage(URL.createObjectURL(file));
} else {
WinJS.log && WinJS.log("No photo captured.", "sample", "status");
}
}, function (err) {
// None taken
});
When I inspect the value of appSession.InAysncMode, I see that the function returns undefined. I suspect it returns undefined because the operation is not complete (i.e. the user has not yet created the photo, and it has not been saved to disc), but I need it in order to cancel out of the camera capture mode programmatically. Does anybody know why it would return undefined instead of the documented IAsyncOperation object?
Thanks!
For reference, here's the answer I posted on the MSDN forum.
To answer your ending question, you can cancel the capture UI by canceling the promise from dialog.captureFileAsync.
Your InAsyncMode flag is undefined because you're assigning to it the return value from captureFileAsync.done() which is, by definition, undefined. It has nothing to do with the API's success.
In the docs, when you see IAsyncOperation, what you get in JavaScript is a promise that will deliver as a result to the completed handler if it succeed. You never see IAsyncOperation or related interfaces in JavaScript directly. The documentation for WinRT is written to be language-neutral, so it's important to understand how those things show up in JS (as promises). In C# you don't see it either, as you just use the await keyword. It's mostly in C++ that you actually encounter the interface.
Anyway, you I believe you want is something along the lines of the code below, where you could eliminate IsAsyncMode in favor of just checking for a non-null promise:
appSession.capturePromise = dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo);
appSession.IsAsyncMode = (appSession.capturePromise != null);
//This will close the capture UI after 5 seconds--replace with whatever logic you need
setTimeout(function () { appSession.capturePromise.cancel(); }, 5000);
appSession.capturePromise.done(function (file) {
if (file) {
} else {
}
}, function (err) {
appSession.IsAsyncMode = false;
appSession.capturePromise = null;
});