检查DOM是否静止不动



有一个非常有趣的问题。我会提供一些背景,因为很多人可能会问为什么有人需要这样的东西。

背景信息

必须为大型复杂的.net web表单应用程序进行单元(集成)测试。目前使用visual studio 2010,nunit,watin 2.1,ie9。已经有一些相当复杂的单元测试,但它们很慢,不太可靠,主要是因为时间问题。因此,必须将执行时间从几个小时减少到更合理的时间,并保持它们的可靠性。

当前问题

我在等待异步请求完成时遇到了一些问题。(需要这样做才能从屏幕上获得更新的页面进行测试。)目前的情况如下:

//Function is called after making an async request to wait for DOM to be updated
public static void WaitForAsyncPostBackToComplete(this Browser browser)
{
int waited = 0;
bool isInPostback = true;
while (isInPostback)
{
if (waited > AjaxWaitTime)
{
throw new Exception(string.Format(
"Looks like Ajax reqest timed out. Test waited {0} milliseconds.",
waited));
}
isInPostback = IsInPostback(browser);
if (isInPostback)
{
// Request is not completed, wait a bit for next polling.
Thread.Sleep(AjaxSleepTime);
waited += AjaxSleepTime;
}
}
// IMPORTANT: Wait for DOM to be actually updated???
Thread.Sleep(300);
}
// Check if something is in postback now.
private static bool IsInPostback(Browser browser)
{
string function =
"(  typeof(Sys) === undefined " +
"|| Sys == undefined || Sys == 'undefined' || Sys==null " +
"|| typeof(Sys.WebForms) === undefined " +
"|| Sys.WebForms==null || Sys.WebForms==undefined|| Sys.WebForms=='undefined'" +
"|| typeof(Sys.WebForms.PageRequestManager) === undefined) " +
"|| Sys.WebForms.PageRequestManager==null || Sys.WebForms.PageRequestManager==undefined|| Sys.WebForms.PageRequestManager=='undefined'" +
"? true " +
": Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack();";
string result = browser.EvalSafely(function);
return Convert.ToBoolean(result);
}

因此,我经常使用池来检查是否使用IsInPostback()函数完成了ajax请求。这似乎非常快速和可靠。

然而,我认为IsInPostback()表示,在实际插入DOM之前,一切都已完成。这意味着我们得到了答案,但我们需要一些时间将其插入此处。因此,我需要那个难看的Thread.Sleep(300)行来等待DOM更新。我想通过某种方式确定DOM何时更新得更精确、更可靠来消除这一行。

真正的问题

有没有什么好的方法可以确定DOM是在异步疯狂的情况下加载到IE9中的?我一直在考虑简单地将整个DOM放入变量中(如果DOM正在更改,它怎么能工作),并轮询以检查其中的更改。如果在最后50毫秒内没有进行更改,我可以停止等待。有什么好方法可以做这样的事情吗?

欢迎有任何想法。。。。

您可以从javascript设置"Ajax请求完成标志",并在C#中进行检查
HTML:

<input type='hidden' id='hdnRequestCompletedFlag' value='0' />

Javascript:

var NoOfCompletedRequests = 0;
var NoOfRequests = 10; // Your number of requests.
$.ajax({
...,
success: function( data ) { // This function same for all the ajax requests.
NoOfCompletedRequests++;
if(NoOfCompletedRequests == NoOfRequests)
$('#hdnRequestCompletedFlag').val('1');
}
});

C#:

private static bool IsInPostback(Browser browser)
{
string function =
"(  typeof(Sys) === undefined " +
"|| Sys == undefined || Sys == 'undefined' || Sys==null " +
"|| typeof(Sys.WebForms) === undefined " +
"|| Sys.WebForms==null || Sys.WebForms==undefined|| Sys.WebForms=='undefined'" +
"|| typeof(Sys.WebForms.PageRequestManager) === undefined) " +
"|| Sys.WebForms.PageRequestManager==null || Sys.WebForms.PageRequestManager==undefined|| Sys.WebForms.PageRequestManager=='undefined'" +
"? true " +
": Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack();";
string result = browser.EvalSafely(function);
return Convert.ToBoolean(result) && (hdnRequestCompletedFlag.Value == '1');
}

这个问题很老了,但它仍然有一些观点,所以我想添加一些关于这个问题的思考。

在阅读了一些文档(对于这样一个特定的案例,这些文档不是很详细)并做了一些实验后,我得出的结论是Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack();只有在DOM更新完全完成后,方法才应退出(返回true)。

然而,很难高精度地使用这种方法,因为在ASP.NET Web Forms中,我们无法完全控制生成的JS。因此,如果由于嵌套的更新面板,在一个用户操作后有多个请求,或者在JavaScript的执行中有一些延迟的更新或不一致,这种方法不是100%稳定的。

最终可能有两种可能的部分解决方案:

  1. 承认这种方法不能在100%的情况下准确工作,并在更高级别的抽象中处理它
  2. 在该函数的顶部添加其他层(以便更好地处理一行中的多个AJAX请求或延迟的请求),并将其与较小的等待时间相结合

无论哪种方式,似乎都没有明确的答案,在线程中没有明确等待的100%情况下都有效。

这个问题非常具体,可能无法得到任何未来可以接受的答案,但我认为它包含了一些有趣的点,所以我将在这里保留这个问题,并接受这些事后思考。

最新更新