有一个相当有趣的问题。我会提供一些背景知识,因为很多人可能会问为什么有人需要这样的东西。
背景信息
必须为大型复杂的.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来消除这条线。
真正的问题
有没有什么好方法可以确定在IE9中加载DOM并且异步疯狂正在进行?我一直在考虑简单地将整个DOM变为变量(如果DOM正在改变它甚至可以工作)并轮询以检查变量。如果没有像过去50ms那样进行任何更改,我可能会停止等待。有什么好方法可以做这样的事吗?
欢迎任何想法......
答案 0 :(得分:1)
您可以从javascript设置'Ajax Requests Completed Flag'并在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');
}
答案 1 :(得分:0)
这个问题已经很老了,但它仍然有一些观点,所以我想考虑在这个问题上添加一些事情。
在阅读了一些文档(对于这种特定情况不是很详细)并做了一些实验后,我得出结论Sys.WebForms.PageRequestManager.getInstance()。get_isInAsyncPostBack();只有在DOM更新完成后,方法才会退出(返回true)。
然而事实证明,使用这种高精度的方法非常困难,因为在ASP.NET Web Forms中我们并没有完全控制生成的JS。因此,如果由于嵌套更新面板而在一次用户操作后有多个请求,或者存在一些延迟更新或执行JavaScript时出现一些不一致,则这种方法不是100%稳定。
最后可能有两种可能的部分解决方案:
无论哪种方式,似乎没有明确的答案在100%的案例中都有效,而且线程中没有明确的等待。
这个问题非常具体,可能无法获得将来可以接受的任何答案,但我认为它包含了一些有趣的观点,因此我将在这里留下问题并接受这些问题。