你如何在Javascript中调试时序问题?

时间:2012-03-26 01:39:10

标签: javascript debugging dom asynchronous timing

我最近碰到了一个熟悉的javascript / jQuery计时错误,并且花了太长时间调试它。我需要的是一个更智能的调试路径来解决这个问题。

具体来说,我的问题是用户输入应该导致Mongo数据库调用,并且结果在经过一些数学运算后发送到显示的输出。但显示的输出很疯狂。但是,一旦我添加了FireBug断点,问题就消失了。那时我知道我有时间问题,但不知道如何解决它。

以下是错误之前的相关代码段:

handleDataCallBack : function(transport) {
   var response = $.parseJSON(transport);

   if(!hasErrors) { this.updatePage(response); }
},

accessDatabase : function(){
   var params = { ... };
   DAL.lookupDatabaseInfo(this.handleCallBackOutputPanel, this, params);
},

calculateValues: function() {
   // some numerical values were updated on the page
}

onDomReady : function() {
// ...
   //bind drop-down select change events
   $('#someDropDown').change(function() {
      me.accessDatabase();
      me.calculateValues();
   });
}

要解决这个问题,我所要做的就是从回调中的onDomReady移动“calculateValues”方法:

handleDataCallBack : function(transport) {
   var response = $.parseJSON(transport);

   this.calculateValues();
   if(!hasErrors) { this.updatePage(response); }
},

问题是数据库在计算开始之前没有响应。当然,回想起来很容易发现。但是我将来可以用什么方法来调试javascript / jQuery中的异步时序问题?这似乎在IDE工具的上下文之外。 FireBug没有帮助。是否有用于跟踪异步Web开发问题的工具?或者也许是一些经过时间考验的方法?

1 个答案:

答案 0 :(得分:2)

我认为你的问题是由此造成的:

$('#someDropDown').change(function() {
    me.accessDatabase();
    me.calculateValues();
});

这个问题是您的计算是在通话结束后立即完成的。看到DB调用是异步的,calculate不会等待它。但是,你可以使用“回调”来做到这一点。我看到你确实尝试实现它,是的,这是正确的。但是,我觉得这更优雅:

calculateValues: function() {
    // some numerical values were updated on the page
},

//since this is your general callback hander
//you hand over the return data AND the callbackAfter
handleDataCallBack: function(transport, callbackAfter) {
    var response = $.parseJSON(transport);

    //you may need to use apply, im lost in scoping here
    callbackAfter();
    //or
    callbackAfter.apply(scope);

    if (!hasErrors) {
        this.updatePage(response);
    }
},

accessDatabase: function(callbackAfter) {
    var params = {};

    //pass callbackAfter to the function,
    //after this is done, pass it to the handler
    DAL.lookupDatabaseInfo(this.handleCallBackOutputPanel, this, params, callbackAfter);
},

onDomReady: function() {
    $('#someDropDown').change(function() {
        me.accessDatabase(function() {
            //send over what you want done after. 
            //we'll call it "callbackAfter" for easy tracing
            me.calculateValues();
        });
    });
}​