Javascript:设置函数的顺序

时间:2011-08-26 11:10:18

标签: 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;
}

最值得赞赏的任何帮助! 比利

3 个答案:

答案 0 :(得分: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);
    }
});

在一般情况下,返回值成为continuation的参数。这里没有使用appointments.download的返回值,因此continuation不带参数。

接下来,重写异步函数以进行延续并在调用中传递延续。

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具有相同的效果。

答案 1 :(得分:0)

目前您正在异步发出请求,这意味着您发出请求并立即从函数返回,您不会等待答案。您应该使您的呼叫同步,我不知道您的connxhr究竟是什么,但他们可能会提供使execute()send()方法同步的方法。例如,如果您将JavaScript自己的XMLHttpRequest的{​​{1}}方法的第三个参数设置为open(),那么false方法将不会返回,直到从服务器收到响应,连接类可能有相同的选项。

答案 2 :(得分:0)

移动调用以将当前约会删除到onload处理程序中。这样你就会删除旧的并立即添加新数据。