JavaScript pattern providing optional callback interface but use promise inside - javascript

I want to create a function, let's say a readConfig function.
readConfig(path [, callback(err, config)])
The callback here is optional. If there is no callback when called, the function will only use synchronous methods (readFile(path) and configParser(string) which return promises) to read the file and directly return the parsed config object. Exceptions are thrown directly. However when callback is provided, the function will use asynchronous methods and call the callback after finished. Exceptions are directly raised to callback but not thrown.
There are many similar codes to do sync and async work, so I want to use one method for both. How can a promise like function detect an async or sync call according to the caller's callback argument? And how can we ensure that the promise will act in synchronous way? Please show me a pattern for that.

I can't speak to the promise acting in a synchronous way, but in JavaScript you can do arguments.length to get the number of arguments passed to a function. If that equals 2 and typeof arguments[1] === 'function', then you have a second argument that is a function.
As for personal taste, I'd recommend just having 2 different functions, one of them ending in Sync, à la http://nodejs.org/api/fs.html. This module is replete with function pairs where one is async and the other isn't.
Also, remember that this is not async code:
function notAsync(cb) {
cb(null)
}
That callback executes in the same tick. You need to wrap it like so:
function async(cb) {
process.nextTick(function(){ cb(null)})
}
or something like that.
Whatever you decide, happy coding.

In this example, I'm using jQuery's deferred api. I wrap the callback in .when which allows you to attach a .then() to the callback, whether it is synchronous or asynchronous with a promise.
The solution should be to use your promise api's when. http://howtonode.org/promises
Live demo (click).
$('#sync').click(function() {
foo(function() {
});
});
$('#async').click(function() {
foo(function() {
var deferred = new $.Deferred();
setTimeout(function() {
deferred.resolve();
}, 500);
return deferred.promise();
});
});
function foo(callback) {
$.when(callback()).then(function() {
console.log('done!');
});
}

Related

How To Convert Synchronous Functions To Asynchronous Functions In JavaScript [duplicate]

I was unsure how node.js was able to realize what functions where async and which were not and how to create a custom async function.
Say I wanted to create a custom asynchronous function. I would be surprised if just because I called my last argument to the async function callback or cb that it would just know its an async function:
function f(arg1, callback){
//do stuff with arg1
arg1.doStuff()
//call callback
callback(null, arg1.result());
}
I tried something like that and it did not work async. How do you tell node.js that f is actually async?
NOTE: this answer was written in 2014, before the existence of async function, and before Promises gaining popularity. While the same principles apply as well, I would recommend reading on Promises before trying to get your head around how they relate to "traditional" callback-driven async functions.
To create a function that calls its callback asynchronously, you have to use some platform-provided async primitive (typically IO-related) on it - timers, reading from the filesystem, making a request etc.
For example, this function takes a callback argument, and calls it 100ms after:
function asyncFn(callback) {
setTimeout(() => {
callback();
}, 100);
}
A possible reason for making a function async when it doesn't need to be, is for API consistency. For example, suppose you have a function that makes a network request, and caches the result for later calls:
var cache = null;
function makeRequest(callback) {
if (!cache) {
makeAjax(result => {
cache = result;
callback(result);
});
} else {
callback(cache);
}
}
The problem is, this function is inconsistent: sometimes it is asynchronous, sometimes it isn't. Suppose you have a consumer like this:
makeRequest(result => doSomethingWithResult(result));
doSomethingElse();
The doSomethingElse function may run before or after the doSomethingWithResult function, depending on whether the result was cached or not. Now, if you use an async primitive on the makeRequest function, such as process.nextTick:
var cache = null;
function makeRequest(callback) {
if(!cache) {
makeAjax(result => {
cache = result;
callback(result);
});
} else {
process.nextTick(() => callback(cache));
}
}
The call is always async, and doSomethingElse always runs before doSomethingWithResult.
Only native functions (with access to the event loop) are asynchronous. You would need to call one of them to get asynchronity for your callback. See What is a simple example of an asynchronous javascript function?.
If you aren't using any, there's hardly a reason to make your function asynchronous.

Purpose of this custom resolve function?

I'm having trouble puzzling this resolve function out...
function _resolve(){
var $deferred = $.Deferred();
return $deferred.resolve.apply($deferred, arguments).promise();
}
I see it being used like
if (availableLanguages.length === 1) {
return _resolve(availableLanguages[0]);
}
and
if (detectedLocale && availableLanguages.indexOf(detectedLocale) > -1) {
// save the locale so the user does not get asked for it again
return _resolve(detectedLocale, true);
}
The _resolve function is a shortcut for creating kind of a dummy jQuery Deferred object, which is initially resolved. They should have rather called it for example _createResolvedPromise which would be more intuitive, but we always used to save some characters don't we.
In general this technique is needed when you have a function which returns a deferred, but in some cases you can have an early return with some value. In this case you cannot just return the value, because the caller expects a deferred, so you have to create a deferred object and immediately resolve it with that value. You can perhaps call these deferred objects constant deferred objects or so.
The apply is used to call the resolve with the optional arguments passed to _resolve. Those arguments will be passed to the done callback later on. See the documentation here.
Calling promise() on the deferred object is nothing more than wrapping it into a promise object, so that the consumer cannot call resolve for example. See the documentation here.
For example, let's assume we want to retrieve something via ajax, but also we cache the results.
var _cachedResult;
function getResults() {
if (_cachedResult) {
// for THIS line they made the _resolve shortcut, with which I could write _resolve(_cachedResult)
return $.Deferred().resolve(_cachedResult).promise();
}
return $.ajax(...).done(function(result) {
_cachedResult = result;
});
}
The caller can use it like this.
getResult().done(function(result) {
// do something with result, which maybe came from the cache
});
Hope it makes sense.
In short, it appears to be wrapping up various calls in a Promise/async fashion.
It's likely that detectLocale is an async function, and they're using _resolve to simply handle it in a synchronous manner. Your _resolve function is returning a Promise, which presumably the consumers of those return values are using.
I would expect to see something like this if you trace it up:
function getLanguages() {
if (availableLanguages.length === 1) {
return _resolve(availableLanguages[0]);
}
return new Promise(); // or something, unless it's checking for null outside
}
function doSomething() {
getLanguages().then(languages => console.log(languages));
}

Callbacks and returning values

I'm stuck with two external libraries and using them together. One only has an async interface and the other requires me to return a value from the callback.
// this function is called as a callback from an external library
// it is required that the function returns a certain value
function onevent()
{
// the callback for the "thirdparty.foo" function
// with the result that must be returned from onevent
function ondone(result) {
// ???
}
// this is a call to a third party library that only has this asynchronous interface
thirdparty.foo(ondone);
// ??? return result;
}
JavaScript is pretty new for me and I was unable to find any solution for this problem.
I'm looking to something to be able to wait for the completion of ondone before returning from onevent. Comparable from C++ would be .wait or .get from a std::future.
One only has an async interface and the other requires me to return a value from the callback.
That's a problem if you have to use the one providing an async interface to satisfy a callback from the one that doesn't. If you do, you simply cannot use them together. There is no way to make the callback from the one expecting a value returned to it by the callback wait for an asynchronous event to complete.
E.g.:
doSomethingExpectingReturnValueFromCallback(function() {
// You cannot use an asynchronous API here to get the value you return
});
If the synchronous lib understood promises (similar to std::future), then you could return a promise, but it doesn't sound like it does.

When are all my functions complete?

I have a set of async functions that issue executeSql commands to drop 2 tables, and have callbacks to create the 2 tables and populate the 2 tables.
I'd like to know when they have ALL completed.
I wouldn't mind if they executed synchronously. In fact, I'd prefer that they ran synchronously!
Q: Would I use the jQuery pipe method to queue up these functions so that they execute in a more traditional way than issuing callbacks?
I want to do something like:
DropTableA();
CreateTableA();
PopulateTableA();
DropTableB();
CreateTableB();
PopulateTableB();
window.location.replace('Index.htm');
Have a look at jQuery's Deferreds and Promises.
In short, here's an example of an async function that executes something asynchronously (setTimeout in this case). When calling the function you get back a promise.
var myFunc = function (value) {
var d = $.Deferred();
setTimeout(function () {
d.resolve(42 * value);
}, 1000);
return d.promise();
};
var promise = myFunc(100);
promise.done(function (res) { console.log(res); });
You can use $.when to execute something when all promieses have been fulfilled, i.e.
$.when(p1, p2, p3).then(...)
If you want to execute them in order you can chain the deferreds using the deffered's pipe.
If they are all sinchronous function (no async call inside those function) you are assured that window.location.replace('Index.htm'); is called after all of them. If you make ajax call you could do
jQuery.ajaxSetup( {async: false});
befare calling the first function and you are ok because all your AJAX call are now synchronous
http://jsfiddle.net/ywL63/
This is where jQuery deferred/promise come into play. Basically you modify your functions like this
function myAction1() {
var dfd = $.Deferred();
$(selector).whatever(function() { dfd.resolve(); // this is one of the callbacks});
return dfd.promise();
}
Then you can go and "wait" for all of the actions to complete with a construct like
$.when(myAction1(), myAction2(), ...).then(function() {
// this will be executed when all the actions finished = resolved
}
If your functions are synchronous, just call them in the right order, as you did in your example.
Assuming instead that your function returns a promise() or an observable object you can simply do
$.when(fn1(), fn2(), ... ).done(function() {
/* here you know that all functions have been returned, as you asked */
})
(note that you can use deferred objects not only for asynchronous tasks)
Edit: if order matters you can use this plugin:
jQuery.whenSync() Plugin For Chaining Asynchronous Callbacks Using Deferred Objects

What does the function then() mean in JavaScript?

I’ve been seeing code that looks like:
myObj.doSome("task").then(function(env) {
// logic
});
Where does then() come from?
The traditional way to deal with asynchronous calls in JavaScript has been with callbacks.
Say we had to make three calls to the server, one after the other, to set up our
application. With callbacks, the code might look something like the following (assuming
a xhrGET function to make the server call):
// Fetch some server configuration
xhrGET('/api/server-config', function(config) {
// Fetch the user information, if he's logged in
xhrGET('/api/' + config.USER_END_POINT, function(user) {
// Fetch the items for the user
xhrGET('/api/' + user.id + '/items', function(items) {
// Actually display the items here
});
});
});
In this example, we first fetch the server configuration. Then based on that, we fetch
information about the current user, and then finally get the list of items for the current
user. Each xhrGET call takes a callback function that is executed when the server
responds.
Now of course the more levels of nesting we have, the harder the code is to read, debug,
maintain, upgrade, and basically work with. This is generally known as callback hell.
Also, if we needed to handle errors, we need to possibly pass in another function to each
xhrGET call to tell it what it needs to do in case of an error. If we wanted to have just one
common error handler, that is not possible.
The Promise API was designed to solve this nesting problem and the
problem of error handling.
The Promise API proposes the following:
Each asynchronous task will return a promise object.
Each promise object will have a then function that can take two arguments, a success
handler and an error handler.
The success or the error handler in the then function will be called only once, after
the asynchronous task finishes.
The then function will also return a promise, to allow chaining multiple calls.
Each handler (success or error) can return a value, which will be passed to the next
function as an argument, in the chain of promises.
If a handler returns a promise (makes another asynchronous request), then the next
handler (success or error) will be called only after that request is finished.
So the previous example code might translate to something like the following, using
promises and the $http service(in AngularJs):
$http.get('/api/server-config').then(
function(configResponse) {
return $http.get('/api/' + configResponse.data.USER_END_POINT);
}
).then(
function(userResponse) {
return $http.get('/api/' + userResponse.data.id + '/items');
}
).then(
function(itemResponse) {
// Display items here
},
function(error) {
// Common error handling
}
);
Propagating Success and Error
Chaining promises is a very powerful technique that allows us to accomplish a lot of
functionality, like having a service make a server call, do some postprocessing of the
data, and then return the processed data to the controller. But when we work with
promise chains, there are a few things we need to keep in mind.
Consider the following hypothetical promise chain with three promises, P1, P2, and P3.
Each promise has a success handler and an error handler, so S1 and E1 for P1, S2 and
E2 for P2, and S3 and E3 for P3:
xhrCall()
.then(S1, E1) //P1
.then(S2, E2) //P2
.then(S3, E3) //P3
In the normal flow of things, where there are no errors, the application would flow
through S1, S2, and finally, S3. But in real life, things are never that smooth. P1 might
encounter an error, or P2 might encounter an error, triggering E1 or E2.
Consider the following cases:
• We receive a successful response from the server in P1, but the data returned is not
correct, or there is no data available on the server (think empty array). In such a
case, for the next promise P2, it should trigger the error handler E2.
• We receive an error for promise P2, triggering E2. But inside the handler, we have
data from the cache, ensuring that the application can load as normal. In that case,
we might want to ensure that after E2, S3 is called.
So each time we write a success or an error handler, we need to make a call—given our
current function, is this promise a success or a failure for the next handler in the promise
chain?
If we want to trigger the success handler for the next promise in the chain, we can just
return a value from the success or the error handler
If, on the other hand, we want to trigger the error handler for the next promise in the
chain, we can do that using a deferred object and calling its reject() method
Now What is deferred object?
Deferred objects in jQuery represents a unit of work that will be
completed later, typically asynchronously. Once the unit of work
completes, the deferred object can be set to resolved or failed.
A deferred object contains a promise object. Via the promise object
you can specify what is to happen when the unit of work completes. You
do so by setting callback functions on the promise object.
Deferred objects in Jquery : https://api.jquery.com/jquery.deferred/
Deferred objects in AngularJs : https://docs.angularjs.org/api/ng/service/$q
then() function is related to "Javascript promises" that are used in some libraries or frameworks like jQuery or AngularJS.
A promise is a pattern for handling asynchronous operations. The promise allows you to call a method called "then" that lets you specify the function(s) to use as the callbacks.
For more information see: http://wildermuth.com/2013/8/3/JavaScript_Promises
And for Angular promises: http://liamkaufman.com/blog/2013/09/09/using-angularjs-promises/
As of ECMAScript6
The .then() method has been included with pure JavaScript with Promises.
From the Mozilla documentation:
The then() method returns a Promise. It takes two arguments: callback
functions for the success and failure cases of the Promise.
The Promise object, in turn, is defined as
The Promise object is used for deferred and asynchronous
computations. A Promise represents an operation that hasn't completed
yet, but is expected in the future.
That is, the Promise acts as a placeholder for a value that is not yet computed, but shall be resolved in the future. And the .then() function is used to associate the functions to be invoked on the Promise when it is resolved - either as a success or a failure.
Before ECMAScript6
To my knowledge, there isn't a built-in then() method in javascript (at the time of this writing).
It appears that whatever it is that doSome("task") is returning has a method called then.
If you log the return result of doSome() to the console, you should be able to see the properties of what was returned.
console.log( myObj.doSome("task") ); // Expand the returned object in the
// console to see its properties.
Here is a thing I made for myself to clear out how things work. I guess others too can find this concrete example useful:
doit().then(function() { log('Now finally done!') });
log('---- But notice where this ends up!');
// For pedagogical reasons I originally wrote the following doit()-function so that
// it was clear that it is a promise. That way wasn't really a normal way to do
// it though, and therefore Slikts edited my answer. I therefore now want to remind
// you here that the return value of the following function is a promise, because
// it is an async function (every async function returns a promise).
async function doit() {
log('Calling someTimeConsumingThing');
await someTimeConsumingThing();
log('Ready with someTimeConsumingThing');
}
function someTimeConsumingThing() {
return new Promise(function(resolve,reject) {
setTimeout(resolve, 2000);
})
}
function log(txt) {
document.getElementById('msg').innerHTML += txt + '<br>'
}
<div id='msg'></div>
Here is a small JS_Fiddle.
then is a method callback stack which is available after a promise is resolved it is part of library like jQuery but now it is available in native JavaScript and below is the detail explanation how it works
You can do a Promise in native JavaScript : just like there are promises in jQuery, Every promise can be stacked and then can be called with Resolve and Reject callbacks, This is how you can chain asynchronous calls.
I forked and Edited from MSDN Docs on Battery charging status..
What this does is try to find out if user laptop or device is charging battery. then is called and you can do your work post success.
navigator
.getBattery()
.then(function(battery) {
var charging = battery.charging;
alert(charging);
})
.then(function(){alert("YeoMan : SINGH is King !!");});
Another es6 Example
function fetchAsync (url, timeout, onData, onError) {
…
}
let fetchPromised = (url, timeout) => {
return new Promise((resolve, reject) => {
fetchAsync(url, timeout, resolve, reject)
})
}
Promise.all([
fetchPromised("http://backend/foo.txt", 500),
fetchPromised("http://backend/bar.txt", 500),
fetchPromised("http://backend/baz.txt", 500)
]).then((data) => {
let [ foo, bar, baz ] = data
console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)
}, (err) => {
console.log(`error: ${err}`)
})
Definition :: then is a method used to solve Asynchronous callbacks
this is introduced in ES6
Please find the proper documentation here Es6 Promises
.then returns a promise in async function.
Good Example would be:
var doSome = new Promise(function(resolve, reject){
resolve('I am doing something');
});
doSome.then(function(value){
console.log(value);
});
To add another logic to it, you can also add the reject('I am the rejected param') call the function and console.log it.
It's about the use of curly braces {} in our arrow functions:
Those 3 examples are doing the same thing (nothing, but have valid grammar, and are a valid Promise chain!)
new Promise(function(ok) {
ok(
/* myFunc1(param1, param2, ..) */
)
}).then(function(){
/* myFunc1 succeed */
/* Launch something else */
/* console.log(whateverparam1) */
/* myFunc2(whateverparam1, otherparam, ..) */
}).then(function(){
/* myFunc2 succeed */
/* Launch something else */
/* myFunc3(whatever38, ..) */
})
console.log("This code has no errors GG!")
The same logic using arrow functions shorthand without {}
new Promise((ok) =>
ok(
/* myFunc1(param1, param2, ..) */
).then(() =>
0 // HEY DID YOU NOTICE! A number that does nothing,
// but otherwise the parsing will fail!
// The code is pretty clean but have a major downside
// As arrow functions without {} can contains only one declaration
// console.log("something") will FAIL here
).then(() =>
"" // HEY DID YOU NOTICE! An empty string that does nothing,
// but otherwise the parsing will fail!
// As arrow functions without {} can contains only one declaration
// We can't add more code here, hence:
// console.log("something")
// Will break the whole promise
// This is likely the error in y(our) code ;)
))
console.log("This code has no errors GG!")
Arrow function with {}
new Promise( (ok) => {
ok(
/* myFunc1(param1, param2, ..) */
)
}).then( () => {
/* myFunc1 succeed */
/* Launch something else */
}).then( () => {
/* myFunc2 succeed */
/* Launch something else */
/* myFunc3(whatever38, ..) */
console.log("something")
/* More console logs! */
console.log("something else")
})
console.log("This code has no errors GG!")
I suspect doSome returns this, which is myObj, which also has a then method. Standard method chaining...
if doSome is not returning this, being the object on which doSome was executed, rest assured it is returning some object with a then method...
as #patrick points out, there is no then() for standard js
doSome("task")must be returning a promise object , and that promise always have a then function .So your code is just like this
promise.then(function(env) {
// logic
});
and you know this is just an ordinary call to member function .
In this case then() is a class method of the object returned by doSome() method.
The ".then()" function is wideley used for promised objects in Asynchoronus programming For Windows 8 Store Apps.
As far as i understood it works some way like a callback.
Find Details in this Documentantion
http://msdn.microsoft.com/en-us/library/windows/apps/hh700330.aspx
Of Cause it could also be the name for any other defined function.
I am about 8 years late, well...anyways, I don't really know what then() does but maybe MDN might have an answer. Actually, I might actually understand it a little more.
This will show you all the information (hopefully), you need. Unless someone already posted this link.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
The format is promise.prototype.then()
The promise and prototype are kind of like variables but not like variables in javascript, I mean like other things go there like navigator.getBattery().then() where this one actually exists but is barely used on the web, this one shows statuses about the battery of the device, more information and more on MDN if you are curious.

Categories