Reputation: 40671
I think I'm probably doing a jQuery faux pas here. Or a JavaScript one for that matter. So stop me if I am! :)
The scenario:
I want to create a function that takes in a string and perhaps some other parameters and then wraps them in a settimeout. Simple thing, but it's a lot cleaner than sticking settimeouts all over my code.
It'd look something like this:
function myFunction(text,interval) {
setTimeout(function(){
// do a bunch of stuff with the text var
},interval)
}
Easy enough. Then I realized I might want to change this together multiple times and to do so, I'd then have to wrap my calls in a nested setTimeouts of their own, and I'm back to messy looking code.
So I was wondering if I could leverage jQuery to make this look better and more usable throughout my code.
I tried this, first making my own custom jQuery function:
$.fn.myFunction = function(text,interval) {
setTimeout(function(){
// do a bunch of stuff with the text var
},interval)
}
Thinking I could then call it with something like this:
$('body')
.myFunction('string1',1000).delay(500)
.myFunction('string2',1000).delay(500)
.myFunction('string3',1000)
This looks so much nicer and makes repetitive use a whole lot leaner. BUT...this doesn't work at all. My questions:
update
Thanks to cookie monster's answer, I now have an updated example:
$.fn.myFunction = function(text,interval) {
return this.queue(function(next) {
setTimeout(function(){
console.log(text);
},interval)
})
};
I'm then attempting it to calling it as such:
$.myFunction('msg1',500).delay(500).myFunction('msg2',500).delay(500).myFunction('msg3',500)
Doing that gives me this error:
TypeError: 'undefined' is not a function (evaluating '$.myFunction()')
So I thought maybe it still needs a selector:
$('body').myFunction('msg1',500).delay(500).myFunction('msg2',500).delay(500).myFunction('msg3',500)
That works!...but just once. It executes the function once, but not again for the other 2 times in the chain. So, a step closer but I still think I'm missing some important concept or syntax.
update 2
JSBin of my almost working code: http://jsbin.com/exAyuCUp/1/
Upvotes: 0
Views: 147
Reputation: 20159
I don't see why you'd bother with doing the setTimeout
when you can just use $.fn.delay
.
I would just use a function without any delay:
$.fn.myFunction = function(text) {
return this.queue(function(next) {
// do a bunch of stuff with the text var
console.log(text);
next();
});
}
and add .delay
where needed:
$('body')
.delay(500).myFunction('msg1')
.delay(500).myFunction('msg2')
.delay(500).myFunction('msg3');
If you don't need to select any element, you can still construct a jQuery object around something else such as a dummy object:
$({}).delay(500).myFunction('msg1');
(You cannot just use $.delay(500).myFunction('msg1')
since the $
object is not a jQuery object inheriting the $.fn
prototype.)
Upvotes: 1
Reputation: 10972
Use .queue()
to make your code work with a .delay()
.
start = Date.now()
$.fn.myFunction = function(text,interval) {
return this.queue(function(next) {
setTimeout(function(){
console.log(text, start - Date.now())
next() // This is mandatory!
},interval)
})
}
- am I even on the right path in thinking this is a viable use of jQuery and custom functions?
Yes, as long as there's a facility to manage an ordered execution of time delayed code, which jQuery does have.
- if it is where am I messing up my logic?
Only thing missing was queuing your code, and retuning a jQuery object
- and finally, does one need to always choose a selector before calling chained jQuery functions? (I selected 'body' just to make the jQuery chain typical, but I'm obviously not doing anything in particular with that jQuery object)
No, a selector simply performs a DOM selection. If you already have a set of elements in your jQuery object, there's no DOM selection needed.
Upvotes: 3