IndexedDb : read and return the object - javascript

Here is the code I'm using to retrieve informations from localdb :
function getById(idObject, typeObjectStore, cb_function)
{
idObject = parseInt(idObject);
var objectStore = db.transaction(typeObjectStore).objectStore(typeObjectStore);
var request = objectStore.get(idObject);
request.onerror = function(event) {
console.log('Error when loading ' + typeObjectStore);
};
request.onsuccess = function(event) {
cb_function(request.result);
};
}
I've read a lot of documentations and I can see that the retrieved content is usually printed directely in the cb_function (callback function).
I'd like to know if it's possible to return the object directly, so I would be able to exploit it in the rest of my code?
Doing something like this doesn't work, but you'll get what I'd like to do :
request.onsuccess = function(event) {
return(request.result);
};
I'm afraid it's not possible considering the asynchronous way of retrieving the data, but I'd like to have a confirmation.
Thank you in advance.
Regards,
Bdloul

It is not possible to return the value in this manner. The callback function is called asynchronously because request.onsuccess is called asynchronously. A return statement is synchronous. You need to know how to work with asynchronous Javascript (AJAX) in order to use indexedDB. Writing AJAX is primarily accomplished with passing callbacks, a continuation passing style (CPS).
Not everyone likes CPS, but it is a very powerful and simple way to express asynchronous operations in code, and sooner or later in every JavaScript programmer's career, you should learn about it.
If you are absolutely set on trying to return something, you can return a promise. Promises are not simple to learn how to use and will take a lot of understanding so proceed with caution.
Personally (my subjective opinion) I would not recommend trying to use Promises. I recommend learning more about Function.prototype.bind. You can use bind to avoid writing nested functions. Bind is also difficult to learn how to use but it also presents an elegant way to avoid nested functions.

Related

Return data async inside emit

I have a background process written in node.js that is using the EventEmitter like this:
var event = { returnValue: undefined };
eventEmitter.emit('name', event, argument);
return event.returnValue; // Example of doing things with event.returnValue.
Other end of the event:
eventEmitter.on('name', (event, argument) => {
var returnValue = await asyncMethod(); // <- This method returns a Promise, so I could use await if possible or some other solution.
event.returnValue = returnValue;
});
I've tried to find an elegant solution to use asynchronous methods, but since EventEmitter does not support asynchronous functions at all, I can't really use await in the function or something similar.
One solution could be to set returnValue to a Promise, but that quickly becomes impractical, specially since some of my functions iterate through multiple asynchronous functions.
I need all the code to complete properly before the first block of code continues and tries to use the event.returnValue.
Is my only solution to use some third party "synchronize", or hasn't anyone at node.js thought of this problem?
There isn't really any problem for me if the thread is blocked while executing, since this is a background process without any GUI.
Since it doesn't really seem to exist any intuitive way to wait for a Promise to resolve synchronously without callbacks, or to use the EventEmitter with async callbacks, I wrote my own simple EventEmitter containing an array, and custom on and emit methods.
It handles asynchronous functions used as parameters properly so I can use it like this:
asyncEmitter.on('name', async (event, argument) => {
event.argument = await asyncMethod(); // Nice and clean code!
});
Of course I could develop it further create a once function and so on, but for me I really only depend on on and emit.
I wonder why the node team hasn't solved this yet?

removing promise dependencies

I'm aware of the power of promises, however I have several old functions that are synchronous:
function getSomething() {
return someExternalLibrary.functionReturnsAValue()
}
console.log(getSomething()); // eg prints 'foo'
Unfortunately, when someExternalLibrary updated, it has removed functionReturnsAValue() and has lumped me with functionReturnsAPromise():
function getSomething() {
return someExternalLibrary.functionReturnsAPromise()
}
console.log(getSomething()); // now prints '[object]'
This of course, breaks absolutely everything written that depends on what used to be a simple value.
Obviously, I'd prefer two things:
ask the original library to keep a synchronous return value. (Not going to happen -- b/c they have refused)
A way to actually wait for a value
I have read numerous articles on why promises are great, ad nauseam, but the simple fact is: If I embrace promises, all I really do is shuffle promises onto some other part of the code, which then must deal with the promise of a value...
Is there a way (in nodejs) to actually wait for a promise to get itself together?
The best I can find is to use coroutines and yield, but really, it's still passing the buck. To be clear, I want the function getSomething to continue to return a value. Is there a way to do it?
Clearly, I fear I've misunderstood something about Promises...
The app is for non-browser implementations and runs purely from the command line. I've been trying to understand how bluebird's reflect() might help, to no avail.
(Yes, I'm aware this question has been asked many times in various formats, but I can't find a suitable answer to the core issue. If anything, I'm looking for the opposite of this question. The closest related (but unhelpful) question I can find is: Managing promise dependencies.)
There's the concept of generator functions. These are a special kind of function in both syntax (asterisk notation) and semantics. Unlike regular functions, generator functions return something that's also new to ECMAScript: iterators. Iterators happen to be objects made specifically to be iterated on, e.g. with the all new for...of loop. They can be also iterated on manually by calling their 'next' method. Each such call produces an object containing two properties: 'value' (iterator's current value) and 'done' (a boolean indicating whether we reached the last value of the iterable). However, the best thing about generator functions is their ability to suspend their execution each time a keyword 'yield' is encountered. Let's have a glimpse of how it all works together:
'use strict';
let asyncTask = () =>
new Promise((resolve, reject) => {
if (Math.random() > 0.5) {
resolve(1);
} else {
reject(new Error('Something went wrong'));
}
});
let makeMeLookSync = fn => {
let iterator = fn();
let loop = result => {
!result.done && result.value.then(
res => loop(iterator.next(res)),
err => loop(iterator.throw(err))
);
};
loop(iterator.next());
};
makeMeLookSync(function* () {
try {
let result = yield asyncTask();
console.log(result);
} catch (err) {
console.log(err.message);
}
});
The short answer
I am told repeatedly: You can't undo functions that have been promisified.
Edit: An upcoming solution
It appears that the ES2017 (although still draft), goes a long way in making promisified code easier to work with:
https://ponyfoo.com/articles/understanding-javascript-async-await
It seems that there is also a node library ready for this support too: https://github.com/normalize/mz.
Using this methodology, having apis converted to Promises won't be so bad (although it still appears that promises still poison the rest of the codebase):
const fs = require('mz/fs')
async function doSomething () {
if (await fs.exists(__filename)) // do something
}
The rest of this answer is just a general commentary on the problem.
Why we need a solution
Let's start with a sample piece of traditional synchronous code, in 3 flavours from more 'older-fashioned' to 'newer':
This is the traditional javascript way, requiring exception based programming to handle unexpected errors:
function getSomething() {
if (someproblem) throw new Error('There is a problem');
return 'foo';
}
However, adding try/ catch statements becomes very laborious and tedious, very quickly.
With the advent of node.js, callbacks were made popular, which nicely circumvented the issue, since each caller was explicitly forced to deal with error conditions in the same callback. This meant less errors in the caller's code:
function getSomething(callback) {
if (callback) {
if (someproblem)
callback(new Error('There is a problem'), null);
else
callback(null, 'foo');
}
return 'foo';
}
Then, the after some teething issues, node.js quickly proved itself for server-side communications, and people were amazed at the speed that asynchronous solutions provided. Node application frameworks like Express and Meteor grew, which focused on this.
Unfortunately, using the same callback scheme quickly became troublesome and the developers dealing in asynchronous code started using Promises in an effort to linearize the code, to make it readable, like the traditional (try/catch) code was.
The problem is that it got evangenlized too much. Everyone started thinking that Promises are the way to go. Personally, I call it a poison on a codebase. Once you have anything that uses Promises, your whole codebase must become asynchronous. This is not always a sensible nor a practical solution, IMHO.
The worst of all side effects is that the above function, even though it is completely synchronous, can be written in Promises too:
var bluebird = require('bluebird');
function getSomething() {
// IMHO, this is ridiculous code, but is increasingly popular.
if (someproblem) return Promise.reject(new Error('There is a problem'));
return Promise.resolve('foo');
}
For those who doubt this is a problem, perhaps should look at the SO question: How do I convert an existing callback API to promises?. Pay particular attention to #3, Node-style callback.
So, for anyone who cares, I would like to suggest that there needs to be a 'pill' for Promises. I urge that we need more than promises: we need results, and sometimes in a timely manner.
Take a look at the default node.js api. It does not use Promises. It also provides both synchronous and asynchronous calls to appropriate parts of the api (eg File System).
For those of you who feel tempted to downvote this answer: that is your prerogative, but there are clear issues on when Promises are not the answer, and I feel strongly that there are cases when we need to be able to re-synchronize decoupled code.
I also apologize for this 'blog-post' styled answer.

Chrome system calls waiting on asynchronous results

I've working on a Chrome extension which is going to collect information from the Chrome.System apis and make use of all that data at once. The problem of course is that these calls are asynchrounous. I've not got a ton of experience with JS, so I want to make sure I'm doing this the easiest way possible.
The only way I can think of is making nested functions in the callbacks.
Something Like:
chrome.identity.getProfileUserInfo(function(userinfo){
getLocalIPs(userinfo.email, function(email, ips){
//keep passing data and nesting here.... and then do something after all calls are made
}
}
This seems like it will get very hard to read the code very quickly. What's the recommened method to do something like this. With synchronous programming, I would want to accomplish something like this:
var email = getEmail();
var ip = getIP();
var processor = getProcessor();
dosomething(email, ip, processor);
Why reinvent the wheel when JavaScript already natively has tools to deal with it?
Specifically, Promises. There's a very good article at HTML5Rock introducing the concept.
You make functions that return promises:
function getEmailPromise() {
return new Promise(function(resolve, reject) {
chrome.identity.getProfileUserInfo(function(userinfo) {
resolve(userinfo.email);
});
});
}
And then you can do exactly what you want:
var email = getEmailPromise();
var ip = getIPPromise();
var processor = getProcessorPromise();
Promise.all([email, ip, processor]).then(function(data) {
// data is [email, ip, processor]
});
Update:
It's 2019 and Promises are well supported in browsers. So see Xan's answer
Original Answer:
The nested functions become a burden a few levels in. I would suggest running each asynchronous call in order, and setting a flag for each callback on completion.
I would then create a function runIfReady() which checks if all required flags are set before launching doSomething(). You can add runIfReady() to the end of every asynchronous callback. Once all of the details are in, the doSomething() will run immediately.
You do not have to worry about launching doSomething() multiple times, because although the callbacks are asynchronous, only one will run at a time.

How to wrap jsonP callback in native javascript Promise?

I'm playin with native Promise to combine a bunch of XmlHttpRequests into one result and I think I got it working, see http://jsfiddle.net/pjs06hdo/
(random calls to flickr api, see the console for what's actually going on in which order)
There might be shorter implementations but with this code I can understand what's going on.
But then there comes the stupid JSONP :-( as it turns out the actual target site does not allow Cross-site requests and I have to use a provided jsonP endpoint (again simulated with flickr) And here I'm stuck: that stupid global callback does not fit into my basic understanding of Promise
I think the solution has to do with explanations in How do I convert an existing callback API to promises?.
I tried to implement this but it works only partially: http://jsfiddle.net/b33bj9k1/ There is no actual output, only console messages, sorry. But there you can see that there are three calls to create the promises but the resolve(), the jsonFlickrApiAsync() gets called only once.
What would be the right way to handle jsonP callbacks with Promise so I can have an Promise.all() to deal with the results as in the XmlHttpRequest version above?
No jQuery please - I want to understand whats really going
This is not a problem with promises, this is a problem with JSONP. Since it uses global callbacks, you need to use different callbacks - with different names - for each request. For Flickr that means you have to use their jsoncallback url parameter. The parameter name may vary for your actual endpoint.
However, your use of promises is indeed weird. Typically you'd use one promise per request, to represent that request's result. You are intentionally creating only one global promise, which cannot work.
function loadJSONP(url, parameter="callback") {
var prop = "loadJSONP.back" + loadJSONP.counter++;
var script = document.createElement("script");
function withCleanUp(r) {
return (x) => {
loadJSONP[prop] = null;
document.head.removeChild(script);
r(x);
}
}
return new Promise((resolve, reject) => {
loadJSONP[prop] = withCleanUp(resolve);
script.onerror = withCleanUp(reject);
// setTimeout(script.onerror, 5000); might be advisable
script.src = url+"&"+parameter+"="+prop;
document.head.appendChild(script);
});
}
loadJSONP.counter = 0;

Asynchronous JavaScript - Callbacks vs Deferred/Promise [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What are the differences between Deferred, Promise and Future in Javascript?
Lately I've been making an effort to improve the quality of my JavaScript applications.
One pattern I've adopted is to use a separate "data context" object to load data for my application (previously I was doing this directly in my view models).
The following example returns data that is initialized on the client:
var mockData = (function($, undefined) {
var fruit = [
"apple",
"orange",
"banana",
"pear"
];
var getFruit = function() {
return fruit;
};
return {
getFruit: getFruit
}
})(jQuery);
In most cases we'll be loading data from the server so we can't return an immediate response. It seems I have two options for how we handle this in our API:
Using a callback
Returning a promise.
Previously I'd always used the callback approach:
var getFruit = function(onFruitReady) {
onFruitReady(fruit);
};
// ...
var FruitModel = function(dataContext, $) {
return {
render: function() {
dataContext.getFruit(function(fruit) {
// do something with fruit
});
}
};
};
However, I can see how it's possible to end up in callback hell, especially when building complex JavaScript applications.
Then I came across the Promises design pattern. Instead of requiring the caller to supply a callback, I instead return a "promise" that can be observed:
var getFruit = function() {
return $.Deferred().resolve(fruit).promise();
};
// ...
dataContext.getFruit().then(function(fruit) {
// do something with fruit
});
I can see obvious benefits of using this pattern, especially since I can wait on multiple deferred objects which could be very useful when loading initialization data for a single page application.
However, I'm keen to understand the pros and cons of each pattern before I start to use either in anger. I'm also interested in whether this is the direction other libraries are going in. It seems to be the case with jQuery.
Here's a link to the fiddle I'm using for testing.
Promises also rely on callbacks behind the scene, so it's not really one vs. the other.
The benefit of callbacks is that they are easy to implement with plain JavaScript (for example in ajax calls).
Promises require an additional abstraction layer, which usually means that you'll rely on a library (not an issue in your case as you are already using jQuery). They are perfect when you deal with multiple async calls in parallel.
From reading the jQuery docs that #Pointy linked to, it sounds like the difference is that the Deferred API allows you to specify more than one function to be called when your request completes:
As of jQuery 1.5, the error (fail), success (done), and complete (always, as of jQuery 1.6) callback hooks are first-in, first-out managed queues. This means you can assign more than one callback for each hook. See Deferred object methods, which are implemented internally for these $.ajax() callback hooks.
See also: deferred.then()

Categories

Resources