jQuery: The Write Less, Do More JavaScript Library

[QUnit] How to test nested asynchronous function calls?

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 | Next >

[QUnit] How to test nested asynchronous function calls?

by gMinuses :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


I'd like to test the following code to make sure:

1. setTimeout calls the function
2. ajax success callback is called

setTimeout(function() {

        $.ajax({
                url: './index.html',
                success: function() {}
        })

}, 100);


If I only have one nested asynchronous test like this, it works:

asyncTest('asyncTest', function() {
        setTimeout(function() {
                console.log(1);
                ok(true, 'success');
                start();

                asyncTest('nested asyncTest', function() {
                        $.ajax({
                                url: './index.html',
                                success: function() {
                                        console.log(2);
                                        ok(true, 'ajax success');
                                        start();
                                }
                        })
                })


        }, 100)

})

But if there are multiple tests, it works, but run out of order:

asyncTest('asyncTest', function() {
        setTimeout(function() {
                console.log(1);
                ok(true, 'success');
                start();

                asyncTest('nested asyncTest', function() {
                        $.ajax({
                                url: './index.html',
                                success: function() {
                                        console.log(2);
                                        ok(true, 'ajax success');
                                        start();
                                }
                        })
                })


        }, 100)

})

asyncTest('another asyncTest', function() {
        setTimeout(function() {
                console.log(3);
                ok(true, 'another success');
                start();

                asyncTest('another nested asyncTest', function() {
                        $.ajax({
                                url: './index.html',
                                success: function() {
                                        console.log(4);
                                        ok(true, 'another ajax success');
                                        start();
                                }
                        })
                })


        }, 100)

})

If you open firebug, you can see the order is "1,3,2,4", which can
cause disasters.

The real world problem is that I use setInterval to periodically check
location.hash to implement a cross-browser "onhashchange" event, and I
bind a function to this event, when the function gets called, it will
make an ajax call. I set a different value to location.hash in every
test to trigger the event, which is actually asynchronous. So how do I
use qunit to test this code?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by Steven Parkes :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Tests don't nest in any particularly meaningful way. When you execute  
test(), you add an entry to the queue of tasks to be processed. So  
your nested test is just adding a new test at the end of the queue,  
independent of the current test.

Do you want something as simple as (untested, so to speak):

test('asyncTest', function() {
   stop();
   expect(2);
   setTimeout(function() {
     ok(true, 'success');
     $.ajax({
       url: './index.html',
       success: function() {
        ok(true, 'ajax success');
        start();
       }
     });
   }, 100);
});



--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by gMinuses :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Thanks! It works!
But I still can't wrap my head around an asynchronous test. How does
the code actually run? The QUnit manual doesn't give much information
on "stop" and "start" functions, it just gives an example about how to
use them. Is there a thorough explanation or tutorial to introduce how
it actually works? Thanks.

BTW, the "module" functions seems not working in the latest version
(October 12, 2009) on github, it doesn't prepend module name to every
test.

On Oct 23, 8:52 am, Steven Parkes <smpar...@...> wrote:

> Tests don't nest in any particularly meaningful way. When you execute  
> test(), you add an entry to the queue of tasks to be processed. So  
> your nested test is just adding a new test at the end of the queue,  
> independent of the current test.
>
> Do you want something as simple as (untested, so to speak):
>
> test('asyncTest', function() {
>    stop();
>    expect(2);
>    setTimeout(function() {
>      ok(true, 'success');
>      $.ajax({
>        url: './index.html',
>        success: function() {
>         ok(true, 'ajax success');
>         start();
>        }
>      });
>    }, 100);
>
> });
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by gMinuses :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


For example, why doesn't the following code work?

asyncTest('yet another asyncTest', function() {
        setTimeout(function() {
            console.log(5);
            ok(true, 'yet another success');
            start();

            stop()
            $.ajax({
                    url: './index.html',
                    success: function() {
                            console.log(6);
                            ok(true, 'yet another ajax success');
                            start();
                    }
            })

        }, 100)
})

The assertion in the ajax success callback doesn't produce a result,
but the callback is indeed called.

On Oct 23, 8:52 am, Steven Parkes <smpar...@...> wrote:

> Tests don't nest in any particularly meaningful way. When you execute  
> test(), you add an entry to the queue of tasks to be processed. So  
> your nested test is just adding a new test at the end of the queue,  
> independent of the current test.
>
> Do you want something as simple as (untested, so to speak):
>
> test('asyncTest', function() {
>    stop();
>    expect(2);
>    setTimeout(function() {
>      ok(true, 'success');
>      $.ajax({
>        url: './index.html',
>        success: function() {
>         ok(true, 'ajax success');
>         start();
>        }
>      });
>    }, 100);
>
> });
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by Steven Parkes :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Oct 22, 2009, at Oct 22,6:53 PM , gMinuses wrote:

> Is there a thorough explanation or tutorial to introduce how
> it actually works?

I just looked at the code.

The key is that the bodies of your tests don't actually run when the  
test() function executes. They are queued up as tasks and then run via  
a loop which is scheduled by a call to setTimeout within qunit.

Without going into the gory details, qunit assumes your test is  
complete unless told otherwise. stop() tells qunit to stop itself  
until told otherwise. So even when your test body finishes, qunit  
doesn't assume the test is over and go on to the next one. Presumably  
you have something that will execute a callback asynchronously,  
possibly runnings ok()s. When your test is done, failed or not, you  
call start() to tell qunit to finish up your test (check expects,  
etc.) and go on to subsequent tests. There's also an option for stop,  
stop(n), which tells qunit to come back to life after n milliseconds  
if it hasn't been told to earlier via start(). You can use this to  
handle cases where, because of a failure in the test, start() never  
gets called which would otherwise cause the test suite to stop midway.

> asyncTest('yet another asyncTest', function() {
>        setTimeout(function() {
>            console.log(5);
>            ok(true, 'yet another success');
>            start();
>
>            stop()
>            $.ajax({
>                    url: './index.html',
>                    success: function() {
>                            console.log(6);
>                            ok(true, 'yet another ajax success');
>                            start();
>                    }
>            })
>
>        }, 100)
> })

qunit doesn't expect to be started and stopped more than once per  
test. There's really no value to that. start and stop are starting and  
stopping quint, not your test. Your code executes as if start() and  
stop() weren't there: they're just signals to qunit. It makes no sense  
to signal qunit to start and then in the next line tell it not to  
start. You should execute stop() once per async test and start() once  
per async test.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by gMinuses :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Wow! This is really informative. Thank you so much! Now I think I
understand why the executing order is the way it is in the second
example.

Thanks again!

On Oct 23, 10:25 am, Steven Parkes <smpar...@...> wrote:

> On Oct 22, 2009, at Oct 22,6:53 PM , gMinuses wrote:
>
> > Is there a thorough explanation or tutorial to introduce how
> > it actually works?
>
> I just looked at the code.
>
> The key is that the bodies of your tests don't actually run when the  
> test() function executes. They are queued up as tasks and then run via  
> a loop which is scheduled by a call to setTimeout within qunit.
>
> Without going into the gory details, qunit assumes your test is  
> complete unless told otherwise. stop() tells qunit to stop itself  
> until told otherwise. So even when your test body finishes, qunit  
> doesn't assume the test is over and go on to the next one. Presumably  
> you have something that will execute a callback asynchronously,  
> possibly runnings ok()s. When your test is done, failed or not, you  
> call start() to tell qunit to finish up your test (check expects,  
> etc.) and go on to subsequent tests. There's also an option for stop,  
> stop(n), which tells qunit to come back to life after n milliseconds  
> if it hasn't been told to earlier via start(). You can use this to  
> handle cases where, because of a failure in the test, start() never  
> gets called which would otherwise cause the test suite to stop midway.
>
>
>
> > asyncTest('yet another asyncTest', function() {
> >        setTimeout(function() {
> >            console.log(5);
> >            ok(true, 'yet another success');
> >            start();
>
> >            stop()
> >            $.ajax({
> >                    url: './index.html',
> >                    success: function() {
> >                            console.log(6);
> >                            ok(true, 'yet another ajax success');
> >                            start();
> >                    }
> >            })
>
> >        }, 100)
> > })
>
> qunit doesn't expect to be started and stopped more than once per  
> test. There's really no value to that. start and stop are starting and  
> stopping quint, not your test. Your code executes as if start() and  
> stop() weren't there: they're just signals to qunit. It makes no sense  
> to signal qunit to start and then in the next line tell it not to  
> start. You should execute stop() once per async test and start() once  
> per async test.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by gMinuses :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


I'm sorry, but after trying and trying, I still have no luck with the
"hashchange" problem. I think I understand what you've said(tests are
queued, and use "stop" will prevent qunit executing another test even
if the current one is finished), but I just can't get those tests
passed. :(

http://dl.getdropbox.com/u/1402827/hashchange/index.html

I've rewritten both the "hashchange" implement and test cases for the
purpose of demonstration, so they are very simple and very clean,
hoping that you won't have problem reading it. Thanks very much!

On Oct 23, 10:25 am, Steven Parkes <smpar...@...> wrote:

> On Oct 22, 2009, at Oct 22,6:53 PM , gMinuses wrote:
>
> > Is there a thorough explanation or tutorial to introduce how
> > it actually works?
>
> I just looked at the code.
>
> The key is that the bodies of your tests don't actually run when the  
> test() function executes. They are queued up as tasks and then run via  
> a loop which is scheduled by a call to setTimeout within qunit.
>
> Without going into the gory details, qunit assumes your test is  
> complete unless told otherwise. stop() tells qunit to stop itself  
> until told otherwise. So even when your test body finishes, qunit  
> doesn't assume the test is over and go on to the next one. Presumably  
> you have something that will execute a callback asynchronously,  
> possibly runnings ok()s. When your test is done, failed or not, you  
> call start() to tell qunit to finish up your test (check expects,  
> etc.) and go on to subsequent tests. There's also an option for stop,  
> stop(n), which tells qunit to come back to life after n milliseconds  
> if it hasn't been told to earlier via start(). You can use this to  
> handle cases where, because of a failure in the test, start() never  
> gets called which would otherwise cause the test suite to stop midway.
>
>
>
> > asyncTest('yet another asyncTest', function() {
> >        setTimeout(function() {
> >            console.log(5);
> >            ok(true, 'yet another success');
> >            start();
>
> >            stop()
> >            $.ajax({
> >                    url: './index.html',
> >                    success: function() {
> >                            console.log(6);
> >                            ok(true, 'yet another ajax success');
> >                            start();
> >                    }
> >            })
>
> >        }, 100)
> > })
>
> qunit doesn't expect to be started and stopped more than once per  
> test. There's really no value to that. start and stop are starting and  
> stopping quint, not your test. Your code executes as if start() and  
> stop() weren't there: they're just signals to qunit. It makes no sense  
> to signal qunit to start and then in the next line tell it not to  
> start. You should execute stop() once per async test and start() once  
> per async test.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by Andrea Giammarchi-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Fri, Oct 23, 2009 at 1:26 AM, gMinuses <gminuses@...> wrote:

If you open firebug, you can see the order is "1,3,2,4", which can
cause disasters.

I am not sure what you are asking for but from logical point of view and generally speaking asynchronous calls do not guarantee order by default so your behavior is kinda expected and not necessary 1,3,2,4
Let's say the first call will take 1 second you'll have 3,4,1,2 which is still expected.

Regards 

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: How to test nested asynchronous function calls?

by DBJDBJ :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Agreed: QUNIT could be documented better.

BTW: Just to be sure "we are by the book" ;o)
I would be so bold to  recommend ,instead of this :

setTimeout(function() {
                                $(window).unbind('hashchange');
                                start();
                        }, 500)

doing this :

var tid = setTimeout(function() {
                                clearTimeout(tid); delete tid ;
                                $(window).unbind('hashchange');
                                start();
                        }, 500)

And in the case of setInterval :

top.intervalTimer = setInterval ( ..... ) ;

$(window).unload( function () {
     clearInterval( top.intervalTimer ) ; delete top.intervalTimer ;
}) ;

It is a somewhat moot point how are the timers implemented and in
which browser and their versions.
So, it does not hurt using them "by the book". I cleraly remember I
had solved some very misterious behaviors in IE6&7 with timer re-
seting,
 but that was a long time ago so I can not exactly say what it was.

--DBJ
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by gMinuses :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message




On Oct 23, 4:11 pm, Andrea Giammarchi <andrea.giammar...@...>
wrote:
> generally speaking asynchronous calls do not guarantee order by default

I think asynchronous tests themselves should guarantee the order. You
fire up two asynchronous calls and their executing order really
doesn't matter. But for asynchronous tests, they should be executed
one after another, that's why a stop & start pair should be used here.

Regards
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: How to test nested asynchronous function calls?

by gMinuses :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


You mean those timers should be reset in the "unload" event? I thought
the browser was gonna do the job. Anyway, thanks for mentioning!

On Oct 23, 4:40 pm, DBJDBJ <dbj...@...> wrote:

> Agreed: QUNIT could be documented better.
>
> BTW: Just to be sure "we are by the book" ;o)
> I would be so bold to  recommend ,instead of this :
>
> setTimeout(function() {
>                                 $(window).unbind('hashchange');
>                                 start();
>                         }, 500)
>
> doing this :
>
> var tid = setTimeout(function() {
>                                 clearTimeout(tid); delete tid ;
>                                 $(window).unbind('hashchange');
>                                 start();
>                         }, 500)
>
> And in the case of setInterval :
>
> top.intervalTimer = setInterval ( ..... ) ;
>
> $(window).unload( function () {
>      clearInterval( top.intervalTimer ) ; delete top.intervalTimer ;
>
> }) ;
>
> It is a somewhat moot point how are the timers implemented and in
> which browser and their versions.
> So, it does not hurt using them "by the book". I cleraly remember I
> had solved some very misterious behaviors in IE6&7 with timer re-
> seting,
>  but that was a long time ago so I can not exactly say what it was.
>
> --DBJ
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: How to test nested asynchronous function calls?

by DBJDBJ :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


clearTimeout() as soon as you can

clearInterval() same as above or in window unload event

On Oct 23, 5:49 am, gMinuses <gminu...@...> wrote:

> You mean those timers should be reset in the "unload" event? I thought
> the browser was gonna do the job. Anyway, thanks for mentioning!
>
> On Oct 23, 4:40 pm, DBJDBJ <dbj...@...> wrote:
>
>
>
> > Agreed: QUNIT could be documented better.
>
> > BTW: Just to be sure "we are by the book" ;o)
> > I would be so bold to  recommend ,instead of this :
>
> > setTimeout(function() {
> >                                 $(window).unbind('hashchange');
> >                                 start();
> >                         }, 500)
>
> > doing this :
>
> > var tid = setTimeout(function() {
> >                                 clearTimeout(tid); delete tid ;
> >                                 $(window).unbind('hashchange');
> >                                 start();
> >                         }, 500)
>
> > And in the case of setInterval :
>
> > top.intervalTimer = setInterval ( ..... ) ;
>
> > $(window).unload( function () {
> >      clearInterval( top.intervalTimer ) ; delete top.intervalTimer ;
>
> > }) ;
>
> > It is a somewhat moot point how are the timers implemented and in
> > which browser and their versions.
> > So, it does not hurt using them "by the book". I cleraly remember I
> > had solved some very misterious behaviors in IE6&7 with timer re-
> > seting,
> >  but that was a long time ago so I can not exactly say what it was.
>
> > --DBJ
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: How to test nested asynchronous function calls?

by DBJDBJ :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Uhm, uhm ... AG is right ... Logically asynchronous events start
immediately upon firing, but they *finish* at an future undetermined
point on the time vector. (or "never")
This is why this paradigm is also called "fire and forget" ... vs
"wait for return" Synchronous paradigm.
Therefore: ordered firing of asynchronous events does not guarantee
ordered finishing.
This is why they are called "asynchronous" , a.k.a. "out-of-sync" ...

--DBJ
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: How to test nested asynchronous function calls?

by Andrea Giammarchi-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

If we need asynchronous calls for a synchronous management, we should use success as "next call if any" event.

var queue = [function(){/*1*/}, function(){function(){/*2*/}}, function(){/*3*/}, function(){/*4*/}], ajax;
$.ajax(ajax = {
               url: './index.html',
               success: function() {
                   queue.shift()();
                   if(queue.length)
                       $.ajax(ajax);
               }
       })

Regards

On Fri, Oct 23, 2009 at 11:50 AM, DBJDBJ <dbjdbj@...> wrote:

Uhm, uhm ... AG is right ... Logically asynchronous events start
immediately upon firing, but they *finish* at an future undetermined
point on the time vector. (or "never")
This is why this paradigm is also called "fire and forget" ... vs
"wait for return" Synchronous paradigm.
Therefore: ordered firing of asynchronous events does not guarantee
ordered finishing.
This is why they are called "asynchronous" , a.k.a. "out-of-sync" ...

--DBJ



--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: How to test nested asynchronous function calls?

by gMinuses :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


I still think the testing order should be determined. It's not the
test cases themselves are asynchronous, it's the functions they are
going to test are asynchronous, and that's why we use a "stop()" to
stop a test case, and use a "start()" in the asynchronous function to
restart the test case, by doing so, we make the tests synchronous,
because if the asynchronous function never gets called, the "start()"
never gets called, and the following test cases won't be executed.

On Oct 23, 6:50 pm, DBJDBJ <dbj...@...> wrote:

> Uhm, uhm ... AG is right ... Logically asynchronous events start
> immediately upon firing, but they *finish* at an future undetermined
> point on the time vector. (or "never")
> This is why this paradigm is also called "fire and forget" ... vs
> "wait for return" Synchronous paradigm.
> Therefore: ordered firing of asynchronous events does not guarantee
> ordered finishing.
> This is why they are called "asynchronous" , a.k.a. "out-of-sync" ...
>
> --DBJ
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by Steven Parkes :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


This should probably be moved off the dev list to the general jquery  
list.

There's a lot of misinformation in here about timers. I'd recommend  
people read John's discussion of timers:

http://ejohn.org/blog/how-javascript-timers-work/.

> I am not sure what you are asking for but from logical point of view  
> and generally speaking asynchronous calls do not guarantee order by  
> default


If we're only talking about JavaScript timers (setTimeout,  
setInterval), callback order is guaranteed to some extent. The html5  
draft spec says that callbacks that are eligible to execute are fired  
in the order queued. There are some corner cases that I'm not sure are  
spec'd, but common cases like two successive calls to setTimeout(fn,0)  
are guaranteed to be executed in the order queued. I haven't tried to  
test this in all browsers, but I haven't seen any violations of this

> var tid = setTimeout(function() {
>                                 clearTimeout(tid); delete tid ;
>                                 $(window).unbind('hashchange');
>                                 start();
>                         }, 500)

I think this is completely unnecessary. A timeout only executes once,  
so clearing it within it's callback should be completely unnecessary.  
Unless there's a real broken browser out there ... The draft spec says  
all intervals are canceled at unload, but I don't rely on unload, so I  
don't quite know what browsers do today in terms of subtle timing. I  
would think it unnecessary but maybe one can write code where order of  
callback firing is critical.

> I think asynchronous tests themselves should guarantee the order.

Two things are getting mixed here. qunit does not queue each  
individual test via setTimeout, so the order of test execution is not  
dependent upon the order of timer callback firing. But, repeating what  
I said above, if you do two setTimeout(fn,0) calls in your test, those  
callbacks should fire in the order you made the setTimeout calls. If  
they have different timeout values, things are less clear.

> Therefore: ordered firing of asynchronous events does not guarantee
> ordered finishing.

Async does not mean concurrent. JavaScript as implemented by most  
browsers is single-threaded. Only one callback is executing at a time.  
So when you do a setTimeout/setInterval call, regardless of what  
timeout you ask for, it cannot start until the current code, whether  
the main script or a callback, finishes. See John's blog article. So  
order of starting === order of finishing.


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by Andrea Giammarchi-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



On Fri, Oct 23, 2009 at 4:30 PM, Steven Parkes <smparkes@...> wrote:

There's a lot of misinformation in here about timers. I'd recommend
people read John's discussion of timers:

I was talking about Ajax calls, no timeouts, but maybe you are not replying to my post :-)

Regards

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by Steven Parkes :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> I was talking about Ajax calls, no timeouts, but maybe you are not  
> replying to my post :-)

Sorry. This stuff does all mix together. XHR can execute async to the  
Javascript thread, but all callbacks are executed on the Javascript  
thread. so any onreadystatechange callbacks won't get executed until  
your application isn't doing anything else. Abstractly, the XHR object  
more or less does a setTimeout(fn,0) of your onreadystatechange  
callback, so timers and XHR do interact.

This is all a simplification of what the html5 draft says, which isn't  
exactly definitive of what any existing browser does, but I find a  
reasonable approximation ...

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by Andrea Giammarchi-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I think now you are the one confusing timers with the fact JavaScript is single threading for each tab ...

I wrote a complete Ajax Guide in 2004 and used LoadVars via Flash before so hopefully I know these things ... in any case for this ML purpose it's always good to remind people how are things

Regards

On Fri, Oct 23, 2009 at 5:15 PM, Steven Parkes <smparkes@...> wrote:

> I was talking about Ajax calls, no timeouts, but maybe you are not
> replying to my post :-)

Sorry. This stuff does all mix together. XHR can execute async to the
Javascript thread, but all callbacks are executed on the Javascript
thread. so any onreadystatechange callbacks won't get executed until
your application isn't doing anything else. Abstractly, the XHR object
more or less does a setTimeout(fn,0) of your onreadystatechange
callback, so timers and XHR do interact.

This is all a simplification of what the html5 draft says, which isn't
exactly definitive of what any existing browser does, but I find a
reasonable approximation ...




--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: [QUnit] How to test nested asynchronous function calls?

by Steven Parkes :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> I think now you are the one confusing timers with the fact  
> JavaScript is single threading for each tab ...
>
> I wrote a complete Ajax Guide in 2004 and used LoadVars via Flash  
> before so hopefully I know these things ...

Certainly possible.

And I know nothing about Flash. Only pure JS, which is not Flash, by  
any means.

Tabs have nothing to do with it; window objects, yes. As far as I  
know, with the exception of Opera, browsers implement one JS thread  
across all windows. (Pretty sure this is true of IE/FF/Safari; don't  
know about Chrome).

The html5 draft puts forward the goal that from the developers point  
of view, JS is single threaded. They imply that if a window object is  
unreachable from another (e.g., because of same origin constraints),  
it could be running in another thread (since there's no chance of  
synchronization issues). But all windows that can reach each other  
must share the same event loop and thus, presumably, the same thread.

As far as I can tell, there's some ambiguity about when JS-visible XHR  
changes can occur. It's clear onreadystate callbacks have to occur on  
the main thread. What I'm not sure about is whether the XHR readystate  
attribute can change in the middle of a callback.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "jQuery Development" group.
To post to this group, send email to jquery-dev@...
To unsubscribe from this group, send email to jquery-dev+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

< Prev | 1 - 2 | Next >