2011-08-26 25 views
1

我正在寫一個鈦應用程序,但我遇到了與我的JavaScript的執行順序有關的問題。Javascript:設置功能的順序

我有一個按鈕上的事件監聽器。這是一個重載按鈕,用於清除表格,使用HTTPClient獲取約會的JSON數組,保存每個約會並刷新表格列表。問題是我正在執行表刪除第一應該清除表,然後我得到的約會,但是當應用程序刷新數據表,就像它做得太快,新的約會尚未保存,因爲我得到一個空的列表。現在,如果我註釋掉db.deleteAll行,每次單擊重新加載時,都會使用新(和現有)約會數據刷新列表。

我需要確保一切都按順序完成,只有當前一個任務完成時。因此,必須在db.DeleteAll後執行appointmentments.download(),並且必須在var allAppointments = db.All()後執行列表刷新。

我認爲問題在於約會.download()函數必須進行HTTP GET調用,然後保存結果,其他函數不會等待完成。

下面是代碼:

btnReload.addEventListener('click', function(e){ 
    var affected = db.deleteAll(); 
    appointments.download(); 
    var allAppointments = db.all(); 
    Ti.API.info(allAppointments); 
    appointmentList.setData(allAppointments); 
}); 

下面是被調用的函數:

db.deleteAll():

api.deleteAll = function(){ 
    conn.execute('DELETE FROM appointments'); 
    return conn.rowsAffected; 
} 

appointments.download():

var appointments = (function() { 
    var api = {}; 
    api.download = function(){ 

     var xhr = Titanium.Network.createHTTPClient(); 
     xhr.onload = function() 
     { 
      var data = JSON.parse(this.responseText); 
      var dl = (data.length); 
      for(i=0; i<dl;i++) 
      { 
      //p = addRow(data,i); // returns the **arr array 
      //Ti.API.info('Saving : '+data[i].first_name); 
      var contact_name = data[i].first_name + ' ' + data[i].last_name; 
      var start_date = data[i].start_date; 
      var reference = data[i].reference; 
      var comment = data[i].comment; 
      var appointment_id = data[i].quote_id; 

      var lastid = db.create(appointment_id, start_date, reference, contact_name, comment); 
      //Ti.API.info(lastid); 
      } 

     }; 
     xhr.open('GET','http://********.co.uk/appointments/download/'); 
     xhr.send(); 

     return; 
} 

任何幫助最感謝! Billy

回答

1

同步調用給你協調(代碼不會執行,直到任何計算取決於完成)免費。使用異步調用時,必須注意協調。這通常意味着將相關代碼作爲函數傳遞給異步代碼。通過的代碼被稱爲「continuation」,這意味着「剩下的計算,從給定的點向前」。傳遞延續被稱爲(不出所料)「continuation passing style」。

要重寫CPS中的代碼,請確定需要協調代碼的位置(調用appointments.download),然後將其餘代碼包裝在一個函數中。

btnReload.addEventListener('click', function(e){ 
    var affected = db.deleteAll(); 
    appointments.download(); 
    function() { 
     var allAppointments = db.all(); 
     Ti.API.info(allAppointments); 
     appointmentList.setData(allAppointments); 
    } 
}); 

在一般情況下,返回值成爲延續的參數。在這裏,沒有使用appointments.download的返回值,所以延續沒有參數。

接下來,在調用中重寫異步函數作爲延續並通過延續。

btnReload.addEventListener('click', function(e){ 
    var affected = db.deleteAll(); 
    appointments.download(
     function() { 
      var allAppointments = db.all(); 
      Ti.API.info(allAppointments); 
      appointmentList.setData(allAppointments); 
     }); 
}); 

... 
api.download = function(_return){ 
    var xhr = Titanium.Network.createHTTPClient(); 
    xhr.onload = function() { 
     var data = JSON.parse(this.responseText); 
     var dl = (data.length); 
     for (i=0; i<dl;i++) { 
      //p = addRow(data,i); // returns the **arr array 
      //Ti.API.info('Saving : '+data[i].first_name); 
      var contact_name = data[i].first_name + ' ' + data[i].last_name; 
      var start_date = data[i].start_date; 
      var reference = data[i].reference; 
      var comment = data[i].comment; 
      var appointment_id = data[i].quote_id; 

      var lastid = db.create(appointment_id, start_date, reference, contact_name, comment); 
      //Ti.API.info(lastid); 
     } 
     _return(); 
    }; 
    xhr.open('GET','http://********.co.uk/appointments/download/'); 
    xhr.send(); 

    return; 
} 

延續命名爲_return,因爲return語句可以模擬成一個延續(默認繼續)。在異步版本中調用_return與在同步版本中調用return的效果相同。

+0

謝謝outis!這工作非常好,感謝CPS的描述! – iamjonesy

0

目前,您正在異步發出請求,這意味着您立即發出請求並從函數返回,您不會等待答案。你應該讓你的電話同步,我不知道你的connxhr真的是什麼,但他們可能提供方法使​​和send()方法同步。例如,如果您將JavaScript自己的XMLHttpRequestopen()方法的第三個參數設置爲false,那麼send()方法將不會返回,直到從服務器收到響應爲止,則您的連接類可能具有相同的選項。

+0

使請求同步是一個壞主意。它將阻止所有的JS調用,直到請求完成。這可能會導致瀏覽器UI停止響應,從而導致它掛起的外觀。 – outis

0

移動調用以將當前約會刪除到onload處理程序中。這樣你將刪除舊的並立即添加新的數據。