JQuery blocking for an asynch initialization - javascript

I'm writing an AngularJS service for a SignalR hub. Here's my factory for the service:
.factory('gameManager', [function () {
$.connection.hub.start();
var manager = $.connection.gameManager;
return manager;
}])
That code would be perfect, except that that .start() call is asynchronous, and the hub has not completed starting by the time the manager is returned. Basically, I want to block until the start is complete before returning the manager. The .start() method returns a Jquery deferred object, which I'm guessing is part of the answer, but I don't know how to use it without a callback function?

Something like the following should do the trick.
app.factory('gameManager', [function () {
return $.connection.hub.start().then(function() {
return $.connection.gameManager;
});
}])
Now your callback function will return a deferred/promise too, so the service consumer will need to be expecting that. Your consuming code might look something like this:
gameManager.then(function(gameManager) {
// do whatever with game manager
gameManager.doSomething();
});
The docs for jquery Deferred are here. In particular, check out Deferred.then().
Note that:
the deferred.then() method returns a new promise that can filter the status and values of a deferred through a function ... These filter functions can return a new value to be passed along to the promise's .done() or .fail() callbacks, or they can return another observable object (Deferred, Promise, etc) which will pass its resolved / rejected status and values to the promise's callbacks...
update:
An alternate approach (and probably the better approach - since it won't require that your consumer handle the promise) is to let the hub initialize completely, before setting up your factory, and kicking off your app controller. Something like this...
$.connection.hub.start().then(function() {
app.factory('gameManager', function() {
return $.connection.gameManager;
});
// ...
// kick off the rest of the app..
});

You will not find what you are looking for, you will have to go with Lee's answer. Javascript is mostly single-threaded and does not allow blocking (with specific exceptions, such as alert window or synchronous ajax call).

Related

A Worker running in the background for knockoutjs vewmodel

I have a viewmodel for a knockoutjs component. In the viewmodel, there is a function init() that executes for several minutes. Because of this, the UI of the component on the browser freezes until the init() finishes its execution.
function myViewModel(){
self = this;
self.x = ko.observable(0);
self.y = ko.observableArray([]);
self.z = ko.observable({});
self.init = function(){
//Need to use JQuery here
//loading stuff from DB via JQuery ajax
//assign retrieved data to x and y and z
}
}
Is there a way to run init() in the background?
I looked at the possibility of Worker, which runs in the background, but Worker needs to use JQuery. If I pass JQuery (and several other JSON objects) to worker via postMessage, like this: worker.postMessage($), then I get the error:
Failed to execute 'postMessage' on 'Worker': An object could not be cloned.
Any idea how to make init() run in the background to avoid frozen UI?
I tried timeout, like below, but UI still freezes:
self.executeAsync = function(func) {
setTimeout(func, 0);
};
self.executeAsync(self.init);
You can use promises.
As for the comments, your problem is that you know how to use all the ajax promises, but you don't know how to implement your own promise.
As you're using jQuery, let's do it with this library. It's only 3 steps
create a deferred object like this: var deferred = $.Deferred();
return a promise from this deferred, so that you can use .then to include the callbacks when the promise is resolve or rejected. For example: return deferred.promise(); or, if you're returning and object, you can return the promise as a member of that object, to check for completion: return { ..., promise = deferred.promise()};
When your code succeeds or fails, resolve or reject your promise, like this: deferred.resolve(); or deferred.reject();
In your case, create a deferred at the beginning of init(), and when all the jQuery ajax are completed, resolve the promise, or reject it, if something goes wrong.
Some notes on Deferred functionality:
If you resolve (or reject) your deferred passing an object, you'll receive that object as a parameter for your callback
You can return an object wrapped in a promise. For example, if your init() returns an object (for example an object implementing an API), you can return that object wrapped in a promise like this: return deferred.promise(retVal);
The implementation of jQuery promises is not Promises/A+ compatible until version 3.0. That has to do with chaining and exception propagation in callback chains. It will not affect you for this case. In the meantime, you can use other promises libraries like Q, or rsvp, which are Promises/A+ compatible, and implement more functionalities.
You can use deferred.notify to signal progress. Then you can specify a progress callback
Documentation for jQuery's Deferred object.
Pseudo code:
init: function() {
var deferred = $.Deferred();
// run your stuff, for example with setTimeout() or setInterval()
// so that the code follows running on the same line
// eventually, your stuff will resolve or reject the deferred/promise
return deferrer.promise();
}
Then you can use callbacks with your init, like usual: init().then(...);
As you don't explain what your init function does, it's not clear if you have to update some observables, or show some controls or whatever when the promise is resolved. That's up to you.
NOTE: I'm afraid you can be doing something wrong if you manipulate DOM objects with jQuery: when using knockout, all the DOM manipulation should be solved with ko bindings. Mixing up both ways of DOM manipulation can soon become cumbersome
You can import jQuery to the Worker script with importScripts().
At the top of your Worker script, just put importScripts('path/to/jQuery') and you'll have access to jQuery. The importScripts function is a global function in the WorkerGlobalScope interface, so all your workers should have access to it.

JavaScript initializing callback parameters down the callback chain

Note: I'm bootstrapping a reactjs app but this is a general JavaScript question.
I have a special module "locationUtils" that I am trying to keep in it's own package, but keeping that code separate is causing an eyesore with callbacks.
When I access one of it's methods I have to send a callback with it that only has one of its parameters initially defined, and in that method I get the other data parameter to initalize the other parameter.
Can I add in undefined parameters later like that in JavaScript, and is it good practice to initial parameters for a callback method as you go down the callback chain in general, or am I making a convoluted newbie mistake?
/********************Module 1******************************/
var bootStrapUI = function(callback) {
locationUtils.findData(findOtherData(callback));
}
//This gets called last to finalize bootstraping
var findOtherData = function(callback,originalFetchedData){
//use originalFetchedData to get more data
//bootStraping program with all rendering data
callback() //sends back a boolean confirming all fetched
}
/**********************Module2**********************************/
var findData = function(findOtherData){
var data = magicGetData();
findOtherData(findOtherData,data);//I initialized a param late here!
}
It's a good Javascript question, callbacks can become a serious hell for the uninitiated, particularly when they are nested and / or the order in which they return is important.
This is where promises come in: they are an essential tool for Javascript development and about to become part of the standard (in EcmaScript 6).
In essence: a promise is an object that is returned from a function with a method (callback) that is called when the asynchronous action (e.g. API call) has been completed. The difference between a promise and a callback is that promises allow you to structure how you handle the callbacks and, importantly, in what order.
I recently wrote a method that had to make 30 api calls with each call dependent on the results of the previous one (this was not a well designed api). Can you imagine trying to do that with callbacks? As it was, I created an array of promises and used jQuery.when() to handle things when all the api calls had completed.
For the moment we need to use a library for promises. jQuery: https://api.jquery.com/jquery.deferred/ is the obvious one but there are various other implementations that do much the same thing.
Update:
The question relates more specifically to the passing of arguments between callbacks and modifying the arguments as execution moves between them. This can be done easily by passing whatever info you need as an argument to your resolve method.
Typically it looks something like this (using jQuery):
var myAsyncMethod = function(info){
var deferred = $.Deferred();
$.getJSON(myUrl,
function(dataFromServer) {
// Do stuff with data
var newData = doSomething(dataFromServer);
deferred.resolve(newData);
});
});
return deferred.promise();
};
// Make initial method call
myAsyncMethod(myInitialData).then(
function(transformedData){
// transformed data from server is returned here.
}
);

Return deferred object or null

I have a function that submits some data. Depending on the state of some boolean, I might not want to submit this data. However, the caller is always expecting a deferred object as the return value to check .done() or .fail(). It seems you cannot return null or return nothing when something expects done/fail (makes sense), so I don't know how to return from this async call.
I can hack in a $.Deferred object and immediately resolve/return it, but that seems like bad design. I can't change the calling method here.
How can I return a deferred object or some other return value that satisfies .done() or .fail() without using a deferred object?
function foo(a) {
bar(a).done(function () {
console.log("done");
}).fail(function () {
console.log("fail");
});
}
function bar(a) {
if (a){
// Could create a $.Deferred and resolve it
return;
}
return doAsync();
}
function doAsync() {
var defer = $.Deferred();
defer.resolve();
return defer.promise();
}
foo(false); // fine
foo(true); // error
http://jsfiddle.net/ma4grjj4/2/
The main problem is that it's usually a design smell to have boolean arguments that changes the process flow of a function.
I think you will agree that doing something like the following makes no sense:
function process(doNotProcess) {
if (doNotProcess) return;
//process
}
In the above example, it would make more sense to simply not call on process() to avoid processing.
"What I would do ideally is in foo skip the entire call of bar, but a
lot of stuff happens inside of bar().done that needs to occur in both
cases"
That code should probably be factored out of the done callback and put in a different function, which would allow you to reuse it without having to call bar.
"I can hack in a $.Deferred object and immediately resolve/return it,
but that seems like bad design."
Creating deferred objects and resolving them right away is a quite standard approach when you need to standardize the use of an API that may have a synchronous or asynchronous implementation.
It's a very good practice to do so because it frees the client from having to rely on implementation details.

Chaining web services calls with promises does not always work

I'm facing an troublesome issue, because it does not occurs every time:
I call webservices with angularJS (hosted in Django/Tastypie), with promises sothat WS2 (Web Service #2) is called only when WS1 has been successfully executed, etc.
The code looks like this:
myfunc = function() {
callPromiseWS1()
.then(function(data){
callPromiseWS2()
})
.then(function(data){
callPromiseWS3()
})
};
WS2 is a POST request that writes stuff in Database.
WS3 is a POST request which uses stuff created by WS2.
Sometimes (and not always), WS3 fails because the object that should have been already created by WS2 does NOT exist.
Of course, if I try to execute the WS3 request later manually, it works.
I have the feeling that WS2 and WS3 are executed in parallel, that's not what I expect.
Any idea? Thank you.
You're missing 3 return statements, but the behavior you're experiencing is because of one in particular:
myfunc = function() {
return callPromiseWS1()
.then(function(data){
return callPromiseWS2(); // this one
})
.then(function(data){
return callPromiseWS3();
})
};
If you don't return the promise that callPromiseWS2 returns, the then() won't know that it's dealing with a promise and just move onto the next then as soon as the synchronous code in callPromiseWS2 completes.
Note that if you're not actually using the data parameter in each step (or if you're just going to pass it right into callPromiseWS2 and callPromiseWS3 as the only parameter), you can simplify this and eliminate the need for two of the above return statements and a lot of the code:
myfunc = function() {
return callPromiseWS1()
.then(callPromiseWS2)
.then(callPromiseWS3);
};
Remember that any function that uses promises should either return the promise, or call .done() at the end.
As a matter of personal preference, I think it's a good idea to use a naming scheme for functions that return promises so that you know they return a promise that needs to be dealt with.
I'm not an expert on promises (and maybe the code you posted was simplified), but the first thing I would check is that the first then returns something, or the second .then will have the same object returned by callPromiseWS1() to work on.
I believe it should be something like:
callPromiseWS1()
.then(function(data){
return callPromiseWS2();
})
.then(function(data){
return callPromiseWS3();
})
But, as I said, I'm not an expert on promises and I don't know if it was just a simplified example of your structure.

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