Event Complete Callbacks with Opal-jQuery - opalrb

I am working on a project that handles multiple jQuery events in succession using the opal-jquery wrapper. jQuery has very effective callback functionality and I am wondering if it is possible to do this in pure ruby with Opal.

You could use a Promise which is a technique to manage long-term asynchronous events and avoid callback-hell. In regular Opal you would do for example:
HTTP.get("url") do |response|
puts "got response"
end
With promises, this becomes:
HTTP.get("url").then do |response|
puts "got response"
end
The difference lies in the then which returns the Promise (see http://opalrb.org/docs/promises/). The code block will be executed when the HTTP get returns with content (or an error).
Also check up this article on how to use promises with opal-jquery
http://opalrb.org/blog/2014/05/07/promises-in-opal/

Related

Ensure a Callback is Complete in Mongo Node Driver

I am a bit new to JavaScript web dev, and so am still getting my head around the flow of asynchronous functions, which can be a bit unexpected to the uninitiated. In my particular use case, I want execute a routine on the list of available databases before moving into the main code. Specifically, in order to ensure that a test environment is always properly initialized, I am dropping a database if it already exists, and then building it from configuration files.
The basic flow I have looks like this:
let dbAdmin = client.db("admin").admin();
dbAdmin.listDatabases(function(err, dbs){/*Loop through DBs and drop relevant one if present.*/});
return await buildRelevantDB();
By peppering some console.log() items throughout, I have determined that the listDatabases() call basically puts the callback into a queue of sorts. I actually enter buildRelevantDB() before entering the callback passed to listDatabases. In this particular example, it seems to work anyway, I think because the call that reads the configuration file is also asynchronous and so puts items into the same queue but later, but I find this to be brittle and sloppy. There must be some way to ensure that the listDatabases portion resolves before moving forward.
The closest solution I found is here, but I still don't know how to get the callback I pass to listDatabases to be like a then as in that solution.
Mixing callbacks and promises is a bit more advanced technique, so if you are new to javascript try to avoid it. In fact, try to avoid it even if you already learned everything and became a js ninja.
Dcumentation for listDatabases says it is async, so you can just await it without messing up with callbacks:
const dbs = await dbAdmin.listDatabases();
/*Loop through DBs and drop relevant one if present.*/
The next thing, there is no need to await before return. If you can await within a function, it is async and returns a promise anyway, so just return the promise from buildRelevantDB:
return buildRelevantDB();
Finally, you can drop database directly. No need to iterate over all databases to pick one you want to drop:
await client.db(<db name to drop>).dropDatabase();

How do you return a MySQL query result from a node REST API

The MySQL JavaScript api is asynchronous.
If I try to write the filling REST Endpoint it fails as the call to MySQL is asynchronous.
#endpoint
String getSometing(){
RetVal = MySQL.asynchApiQuery(“someSql”)
return RetVal;
}
It will fail as RetVal will not be populated when the function returns.
I’ve spoken to a number of people who rave about JavaScripts asynchronous capabilities yet they have been unable to solve this simple synchronous problem
I’m hoping for a simple answer but so far all I’ve got is observable,promise, subscribe, continuation all of which cannot return the query as a promise simply creates a new thread that cannot be associated with the invoked of the REST api.
Any answer to this should return RetVal and not simply print it.
Look forward to a simple answer.
It's asynchronous but it has something named "callback functions". You can use them to decide what's going to happen with data after a mysql query
Example:
db.query("sqlquery",(err,data)=>{console.log(data)})

Unexpected Node.js program flow

I am new to node.js and working through the API. In the stream module docs I came across this example of the "unpipe event" (actually a fusion of two examples in the docs).
const fs = require("fs);
const writable = fs.createWriteStream("write.txt");
const readable = fs.createReadStream("read.txt");
readable.pipe(writable);
setTimeout(function(){
console.log("Stop writing to file.txt");
readable.unpipe(writable);
console.log("Manually close the file stream");
writable.end();
}, 0);
writable.on("unpipe", function(src){
console.log("Something has stopped piping into the writer");
});
I can't understand the following console.log order:
"Stop writing to file.txt"
"Something has stopped piping into the writer"
"Manually close the file stream"
Given the setTimeout callback is running - which is the first phase of the event loop as I understand - how on earth does the callback for the "unpipe" event start to run before the setTimeout callback has finished.
Originally I had the setTimeout firing after a time above zero seconds, however I was finding that the unpipe call back was always called first. I reasoned that my computer was reading the file always first before the setTimeout was ready. (Although I can't see any mention in the docs about the completion of the write to the file eliciting the "unpipe" event, but this makes sense I suppose). However I can't for the life of me reason how the above program flow is occurring. Thanks in advance for any help.
As specified by the node.js documentation:
The EventEmitter calls all listeners synchronously in the order in which they were registered.
That is, when .emit is called, it synchronously runs through all listeners for the emitted event and calls them.
Note that if necessary you can wrap your callback code in process.nextTick to ensure that it will always run asynchronously, but in your case it's likely that's unnecessary.
Also the source of the call to .emit (the emission of the event) will often be asynchronous.

What does "dispatch()" mean/do, and why is it used when we have .then() and .catch()

I am new to ES6 and advanced javascript. I have seen examples of code using the axios http client like this:
axios.xxx(...).then((res) => dispatch(success(res)) , (err)=> dispatch(error(err)))
whereas I am doing:
axios.xxx(...).then(function(res){...}).catch(function(err){...});
I tried to look up dispatch on MDN but only found DispatchEvent... which is not the same? I ask because although my code works, I am finding http error codes like 403 etc from my api are handled as errors by axios, while i would prefer to handle them myself in the app. (Update: when I added the dispatch tag to this question, I saw a brief summary of the meaning but I am still confused).
What is the reason or advantage for using dispatch? Is "dispatch()" part of axios, or ES6, or nodejs? thx.
When I see dispatch I immediately think of redux-thunk (a popular middleware for Redux). It is a good example of why passing dispatch is useful. Basically dispatch is used as a callback which gets invoked once some async action is complete. In redux-thunk dispatch is simply a function which dispatches an action to the Redux store after, let's say, you fetch data from an API (which is asynchronous). You can pass any function you like to .then() or .catch() of some Promise and it will be invoked upon success or failure.

With when.js how can I convert a promise to a Node.js style callback?

I'm using IcedCoffeeScript.
I want to write this:
User.find(id).always esc done or await User.find(id).always defer e, user
But Promise#always is deprecated in when.js.
Is there another way?
Promise#always is deprecated in when.js and will be removed in an upcoming version.
However, promise.always(onFulfilledOrRejected, onProgress) is nothing but a shortcut for .then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress). So instead of using
.always(handler)
You will have to use
.then(handler, handler)
If may affect your code if you were using inline functions for .always as with .then it would be better to extract them as separate functions.
Authors of when.js recommend using promise.ensure instead of promise.always. More details here.
promise.ensure is safer in that it cannot transform a failure into a success by accident (which always could do simply by returning successfully!).
I hope that will help.

Resources