日期:2014-05-16  浏览次数:20698 次

為何setTimeout的ajax可以實現有序自調用
$(document).ready(function(){

	var FREQ = 10000 ;
	var repeat = true;
	
	function showFrequency(){
		$("#freq").html( "Page refreshes every " + FREQ/1000 + " second(s).");
	}
	
	function startAJAXcalls(){
	
		if(repeat){
			setTimeout( 
			    function() {
					getXMLRacers();
					startAJAXcalls();
				}, 	
				FREQ
			);
		}
	}
	
	function getXMLRacers(){
		$.ajax({
			url: "finishers.xml",
			cache: false,
			dataType: "xml",
			success:  function(xml){
				
				$('#finishers_m').empty();
				$('#finishers_f').empty();
				$('#finishers_all').empty();
				
				$(xml).find("runner").each(function() {
					var info = '<li>Name: ' + $(this).find("fname").text() + ' ' + $(this).find("lname").text() + '. Time: ' + $(this).find("time").text() + '</li>';
					if( $(this).find("gender").text() == "m" ){
						$('#finishers_m').append( info );
					}else if ( $(this).find("gender").text() == "f" ){
						$('#finishers_f').append( info );
					}else{  }
					$('#finishers_all').append( info );
				});
				
				getTimeAjax();
			}
		});
	}

	function getTimeAjax(){
	$('#updatedTime').load("time.php");
		/*
		var time = "";
		$.ajax({
			url: "time.php",
			cache: false,
			success: function(data){
				$('#updatedTime').html(data);
			}
		});
		*/
	}
	
	$("#btnStop").click(function(){
		repeat = false;
		$("#freq").html( "Updates paused." );
	});

	$("#btnStart").click(function(){
		repeat = true;
		startAJAXcalls();
		showFrequency();
	});	

	showFrequency();
	getXMLRacers();
	startAJAXcalls();
});
?

這是在HeadFirst JQuery第八章中出現的,爲什麽其中的
startAJAXcalls可以實現有序自調用呢?萬一getXMLRacers()調用卡住超過十秒,它還能實現有序嗎?

?

它裏面說了很多:

Since we wait until the last call to our function is finished, we use the setTimeout function.

?

Self-referencing functions
A self-referencing function calls itself during its normal operations. Such functions can be particularly
useful when you need to wait for the function’s currently running operation to complete before running
it again. Combine this with a setTimeout call, and you can schedule a function to run but only keep
going if the previous call to the function was successful. Otherwise, it won’t reach the call to itself in the
code, and hence it won’t be called again.

?

其實我理解主要是setTimeout中的函數的調用是多線程,因此不會阻塞主線程,還有一個前提就是getXMLRacers()不會卡住超過10秒,否則就會出現startAJAXcalls並行運行的局面,不能保證有序了。

?

現在這樣測試:

FREQ=100;

function startAJAXcalls(){
    if(repeat){
        alert("start");
        setTimeout(
            function() {
                alert("xml racers started");
                getXMLRacers();
                sleep(5000);
                alert("ajax calls started");
                startAJAXcalls();
                alert("ajax calls finished");
            },    
            FREQ
        );
        alert("end");
    }
}
   
function sleep(numberMillis) {
    var now = new Date();
    var exitTime = now.getTime() + numberMillis; 
    while (true) {
        now = new Date();
        if (now.getTime() > exitTime)   
            return;
    }
}
?

發現運行中這些alert數量都是1:1,而且alert("ajax calls finished");每次都會執行到,真是奇之怪哉,不同於java中的遞歸表現。真如其所說,self-referencing調用會等上次調用執行完畢后才會去調用,但是爲什麽呢?是什麽機制。

?

?