Jquery deferred.done doesn't recognize result type of function - jquery-deferred

I created the code below which generates the error: Uncaught TypeError: Cannot read property 'done' of undefined. I think I understand what's happening here, def() isn't a deferred until the timeout expires and the .done tries to run straight away, but what I don't understand is if this doesn't work, why do deferreds work at all? How does .done ever know that the code in front is a promise/deferred given that it may not have resolved yet? Please explain syntax that will make it work, because this is doing my head in.
To put it bluntly I wish that .done would just shut up and wait like it's meant to (I understand that it would have to be a method of all objects and wait until they've resolved even if it's not to a deferred, but if you've typed .done why wouldn't you want that?). Or does it work that way, but I just don't know how to use it properly?
Please don't just refer me to an existing guide/post on jquery deferred unless it explicitly resolves my confusion.
Thanks.
jsfiddle here
function def() {
d = new $.Deferred;
setTimeout(function(){
d.resolve();
return d;
},1000)
}
def().done(function(){
console.log('test');
});

You have to return the promise value from def() itself, not from the setTimeout().
function def() {
var d = $.Deferred();
setTimeout(function(){
d.resolve();
},1000)
return d;
}
def().done(function(){
console.log('test');
});
Returning a value from setTimeout() doesn't do anything. def() has long since finished executing (and returning nothing) and the return value from setTimeout() just goes back into part of the system runtime that calls timer callbacks and is ignored.
I also made a couple other corrections:
Declared d as a local variable (not an implicit global) by putting var in front of its declaration.
Changed the creation of the deferred to $.Deferred(). While, I think the new construction might work, that isn't how jQuery has documented its usage.

Related

Passing Promise to first argument of `.then`

My question is: Is it okay to pass a promise to the first argument of .then? (Assuming that I'm not interested in the returned value of the previous promise and I just want to chain promises together).
Someone told me that if I do this, a new promise will be created
implicitly (unnecessarily), and I might face issues handling errors
bellow in the promise chain.
I know that if you don't explicitly return a promise in an async method the result will be implicitly wrapped. In this case, .then should not wrap the argument in a promise since the argument is already a promise :/
Example:
async function asyncFunc() {
//async function (return Promise)
}
// I know this is okay
somePromise.then(() => asyncFunc());
// BUT... is this okay?
somePromise.then(asyncFunc());
Is it okay to pass a promise to the first argument of .then?
Yes.
Someone told me that if I do this, a new promise will be created implicitly (unnecessarily)
Promise.prototype.then() returns a new promise either way.
// BUT... is this okay?
somePromise.then(asyncFunc());
No, it is more or less the same as:
const p = asyncFunc()
somePromise.then(p);
You execute the function before somePromise actually resolves. What you probably want instead is somePromise.then(asyncFunction). This will properly chain the promises after each other.
Someone told me that [...] I might face issues handling errors bellow in the promise chain.
No. This does not change the behaviour of the promise chain as long as long as there is a catch at the end of the chain.

Promise.resolve inside then() method does not pass its resolved value

I found an interest thing about Promise. When I run the following codes, it gave me the output of 'aa' as oppose to 'bb', which confused me a lot. Does anyone understand why and give a explanation, please? Thanks!
Promise.resolve('aa')
.then(Promise.resolve('bb'))
.then(console.log);
Well, you're misusing a .then() handler so it is no surprise that you don't get the desired answer.
A .then() handler should be passed a function reference. You are passing it a promise which it dutifully ignores because it's not a callable function.
When you do this:
.then(Promise.resolve('bb'))
That executes Promise.resolve('bb') immediately and passes the return result (which is a promise) to .then(). So, you're passing a promise to .then() when you should be passing a function reference. If you change your code to this, then you will get what you expect:
Promise.resolve('aa')
.then(function() {return Promise.resolve('bb');})
.then(console.log);
Remember, the point of passing something to .then() is that it can be executed LATER when the parent promise resolves/rejects. So, for that to be possible, you have to pass a function reference that can be called by the promise infrastructure at some later time.
Using ES6 syntax, you could shorten to this:
Promise.resolve('aa')
.then(_ => Promise.resolve('bb))
.then(console.log);

DalekJS and Mithril: Test are too fast

I use Dalek to test my sample to-do application written with help of Mithril framework.
Everything goes fine until .type() comes in.
If I .type() something in input that have bi-directional binding m.prop with m.withAttr and then assert values of that field i get strage behaviour. Instead "test title" I get "tsttle". It seems that test are running too quickly for Mithril to capture changes and render them back to DOM.
If assertions for input equality is removed — all works just fine.
Is there any workaround, can I slow down type process?
P.S. I use Chrome browser as test runner.
That definitely is an interesting issue, the problem is though, that Dalek can't control the speed of the letters typed. This is due to the fact that the JSON-Wire Protocol does not give us a way to handle that, see here
One thing you could do, even if it seems like overkill, is to add a long function chain with explicit waits, like this:
.type('#selector', 'H')
.wait(500)
.type('#selector', 'e')
.wait(500)
.type('#selector', 'l')
.wait(500)
.type('#selector', 'l')
.wait(500)
.type('#selector', 'o')
You also could go ahead & write a utility function that handles that for you
function myType (selector, keys, test, wait) {
var keysArr = keys.split('');
keysArr.forEach(function (key) {
test.type(selector, key).wait(wait);
});
return test;
}
And then use it in your test like this:
module.exports = {
'my test': function (test) {
test.open('http://foobar.com');
myType('#selector', 'Hello', test, 500);
test.done();
}
};
Mithril, as of when I'm writing this, does a re-render on onkey* events. An option to avoid this is coming.
You could use attr::config at present to handle the onkey* events as this will not cause a rerender. For example:
m('input', {config: addHandler});
function addHandler (el, isInitialized, context) {
if (!isinitialized) {
el.addEventListener('onkeyup', keyHandler, false);
}
}
function keyHandler (event) { /* do something with key press */ }
Its possible {config: addHandler, onchange: m.withAttr('value', mpropData)} will do what you want, but I don't know Dalek. If its doesn't, then you can consider updating mpropData inside keyHandler.
Mithril renders asynchronously in response to event handlers (basically so that related groups of events like keypress/input all get a chance to run before redrawing)
You could try a few things:
if you have access to your data model from your test, you could run your assertion against that model value (which is updated synchronously), as opposed to using the DOM value which only gets updated on the next animation frame
otherwise, you could force a synchronous redraw by explicitly calling m.render (yes, render, not redraw) before running the assertion, to ensure the view is actually in sync w/ the data model
alternatively, you could try waiting for one animation frame (or two) before running the assertion

Waiting for Loader

Edit: Looks like I typoed today. Thanks, Antoine.
I need to fetch the published dimensions of any given swf. Until now, I've relied on loaderInfo for this, however, I've recently discovered that those properties are not fully loaded even after this is addedToStage. Checking if loaderInfo.hasOwnProperty("width") is pointless, as the property already exists, but that property itself is a getter function which returns the error. Therefore, to avoid a Error #2099, I'm querying a property that only shows after being fully loaded, and doing it inside a try/catch statement. Problem is... the catch isn't... catching?
var loaderLoaded:Boolean = false;
try { loaderLoaded = (this.loaderInfo.width > 0) ? true : false; } catch (e:Event) {}
trace("Loader loaded: " + loaderLoaded);
As stated before, this results with
Error #2099: The loading object is not sufficiently loaded to provide this information. at flash.display::LoaderInfo/get width()
I need to either fix the try/catch statement, or find another way of polling swf dimensions.
If you just copy/pasted this, you wrote catch(e:Event) instead of catch(e:Error).
You cannot catch an event.

Node js: Assign mysql result to requests

Previously I was PHP developer so this question might be stupid to some of you.
I am using mysql with node js.
client.query('SELECT * FROM users where id="1"', function selectCb(err, results, fields) {
req.body.currentuser = results;
}
);
console.log(req.body.currentuser);
I tried to assign the result set (results) to a variable (req.body.currentuser) to use it outside the function, but it is not working.
Can you please let me know a way around it.
The query call is asynchronous. Hence selectCb is executed at a later point than your console.log call. If you put the console.log call into selectCb, it'll work.
In general, you want to call everything that depends on the results of the query from the selectCb callback. It's one of the basic architectural principles in Node.JS.
The client.query call, like nearly everything in node.js, is asynchronous. This means that the method just initiates a request, but execution continues. So when it gets to the console.log, nothing has been defined in req.body.currentuser yet.
You can see if you move the console log inside the callback, it will work:
client.query('SELECT * FROM users where id="1"', function selectCb(err, results, fields) {
req.body.currentuser = results;
console.log(req.body.currentuser);
});
So you need to structure your code around this requirement. Event-driven functional programming (which is what this is) can be difficult to wrap your head around at first. But once you get it, it makes a lot of sense.