Ajax 작업이 예기치 않게 실패했습니다.
<p>我们在网站上的许多地方使用了 ajax。一个实例有时会表现得不规则,就像 ajax 调用失败一样。它仅在一个特定位置 - 所有其他位置都按预期工作。</p>
<p>发生故障时,用户会收到操作失败的错误消息。</p>
<p>我们无法重现该故障。它总是只适合我们。大多数用户没有遇到这个问题。少数确实这样做的人有时会报告说他们稍后再试一次并且成功了。</p>
<p>我们可以通过重命名ajax脚本来模拟失败。然后,当尝试操作时,ajax 调用失败,我们收到相同的错误消息。然而,我们没有任何理由相信该错误是由于无法访问 ajax 脚本引起的,尽管有可能。如果是这样的话,那么我们的其他 ajax 脚本也会出现同样的问题。</p>
<p>我们已经想出了一个解决方法。如果用户在尝试操作之前进入隐身模式,则可以避免该问题。</p>
<p>隐身模式解决方法表明它可能与 cookie 有关。因此,我们尝试以某种方式干扰 cookie,以尝试重现该问题。什么都没有成功。</p>
<p>为了帮助排除故障,我们在错误消息中添加了额外的诊断信息,但到目前为止,除了类似于“错误”的信息之外,还没有任何结果。下面是一些代码,显示了我们如何尝试获取更多信息:</p>
<pre class="brush:php;toolbar:false;">error: function (jqXHR, textStatus, errorThrown)
{
// alert('read-unread error');
ajaxError('Read-Unread', textStatus, errorThrown); // TODO comment out to suppress the error reporting
},</pre>
<p>为了完整起见,我在下面包含了完整的 JavaScript 函数。</p>
<p>建立一个简单的测试环境来演示问题效果并不好,因为它会过于简化真实环境,从而破坏了其测试价值。我们认为唯一合理的测试是模拟用户正在做的用例。不幸的是,这很复杂,因为它涉及在我们的系统上创建个人资料,尝试使用该系统与其他成员进行通信,从其他成员那里获得一些响应通信,然后尝试回复此类通信。这会重新创建用例以及发生故障的位置。不幸的是,我们再次怀疑它仍然永远不会触发我们的失败——玩具系统也会“正常工作”。</p>
<p>如果每次都发生在每个用户身上,那将是一回事,但事实并非如此。某些时候只有部分用户使用,并且仅用于我们网站上众多 ajax 使用中的一种。一旦它开始发生,至少在一段时间内该用户可以重复。</p>
<p>我的问题:</p>
<ol>
<li><p>我们如何创建一个精简版本的环境,以便我们可以让 stackoverflow 社区值得一看,而不是模拟我们网站的使用?</p>
</li>
<li><p>“隐身模式”解决方法是否可以提供任何见解来了解出现的问题?</p>
</li>
<li><p>除了诊断在大多数情况下都能正常工作的代码之外,了解其他 Ajax 故障模式也会很有帮助。举个虚构的例子,比如“某些系统太慢,ajax 超时”。</p>
</li>
</ol>
<p>[JavaScript 函数。注意:由于某种原因,我无法将函数的前几行放入代码标记中。]</p>
<pre class="brush:php;toolbar:false;">function toggleReadUnread(usertypeid, opp_user_label_short, principalid, repid, contactuid, value) {
var new_response = (value) ? 'read' : 'unread';
var prefix = '#' + contactuid;
$('#ur-read-unread-text').html(new_response);
$('#read-unread-dialog').dialog
({
show: "fade",
title: "Change to " + new_response + "?",
modal: true,
resizeable: false,
width: getDialogWidth(400, .9),
maxWidth: 400,
fluid: true,
buttons:
{
Ok: function ()
{
$(this).dialog('close');
$.ajax(
{
// async: false
type: 'POST',
url: '/ajax/set-var.php',
// url: '/ajax/tr-toggle-status.php',
data:
{
'which_function': 'read-unread',
'principalid': principalid,
'repid': repid,
'usertypeid': usertypeid,
'value': value
},
error: function (jqXHR, textStatus, errorThrown)
{
// alert(jqXHR.responseText);
ajaxError('Read-Unread', textStatus, errorThrown);
},
success: function (data, textStatus, jqXHR)
{
if (data)
{
var connector = '\', \'';
if (value)
{
$(prefix + '-unread').remove();
$('<i id="' + contactuid + '-read" class="fa fa-envelope-open tooltip" onclick="toggleReadUnread(\'' + usertypeid + connector + opp_user_label_short + connector + principalid + connector + repid + connector + contactuid + '\'' + ', false);"><span id="' + contactuid + '-read-unread-tt" class="tooltiptext">You have no unread messages from this ' + opp_user_label_short + '</span>').insertAfter(prefix + '-read-unread-placeholder');
}
else
{
$(prefix + '-read').remove();
$('<i id="' + contactuid + '-unread" class="fa fa-envelope tooltip" onclick="toggleReadUnread(\'' + usertypeid + connector + opp_user_label_short + connector + principalid + connector + repid + connector + contactuid + '\'' + ', true);"><span id="' + contactuid + '-read-unread-tt" class="tooltiptext">You have a new message from this ' + opp_user_label_short + '</span>').insertAfter(prefix + '-read-unread-placeholder');
$('.tc-' + contactuid).hide();
}
jConfirm('Success', 'Messages marked "' + new_response + '"');
}
}
})
},
Cancel: function () {
$(this).dialog('close');
}
}
})
}</pre>
<p>编辑1:</p>
<ol>
<li><p>我们仍然与用户遇到此问题。我们仍然无法在内部重现它。</p>
</li>
<li><p>隐身模式可以防止问题发生。虽然这应该是一个很好的线索,但到目前为止还没有帮助我们。它似乎指向会话和缓存问题。我们已经排除了过时的缓存问题。</p>
</li>
<li><p>它是间歇性的,仅影响少数用户。稍后甚至该用户也将不再遇到问题。再次似乎与缓存相关。</p>
</li>
<li><p>我们添加了诊断信息,有时在 ajax 错误抛出中显示“禁止”。检查这意味着它与跨域操作有关。没有进行跨域活动;所有请求都发送到我们自己的服务器。</p>
</li>
<li><p>我们向一些用户询问了他们的扩展程序。在一种情况下,他们没有安装扩展;在另一种情况下,他们只有 Chrome 的 Grammarly 扩展。我们使用该扩展进行了测试,但仍然无法重现该问题。</p>
</li>
<li><p>发生错误时,会显示一个对话框。单击该对话框上的“确定”后,其余操作应该继续进行,因为该对话框没有阻止任何内容。但是,用户报告说,如果不处于隐身模式,他们无法完成该操作。</p>
</li>
</ol>
<p>编辑2:</p>
<p>我开始研究 https-access.log。虽然大多数对 ajax 文件的访问都会返回 200,但也有返回 302 的情况。其含义是“文件已移动”。但文件并未移动,不久之后就恢复正常访问。</p>
<p>这是访问日志的摘录,显示了一系列 200 响应,其中散布着一些 302,然后恢复 200。</p>
<pre class="brush:php;toolbar:false;">108.221.39.97 - - [13/Jan/2023:10:07:52 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
108.221.39.97 - - [13/Jan/2023:10:08:34 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
108.221.39.97 - - [13/Jan/2023:10:09:56 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
73.176.158.231 - - [13/Jan/2023:10:10:21 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:15:07 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
184.178.239.162 - - [13/Jan/2023:10:15:18 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?reply=tr-28560-80354" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76"
74.73.226.238 - - [13/Jan/2023:10:15:20 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
24.144.188.195 - - [13/Jan/2023:10:15:22 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:15:28 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:15:34 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:15:37 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:15:49 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
72.38.12.208 - - [13/Jan/2023:10:15:54 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?reply=tr-43850-7444" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76"
74.73.226.238 - - [13/Jan/2023:10:16:07 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
74.73.226.238 - - [13/Jan/2023:10:16:19 -0600] "POST /ajax/set-var.php HTTP/2.0" 302 - "https://www.rephunter.net/track-relationships.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
108.221.39.97 - - [13/Jan/2023:10:17:23 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
108.221.39.97 - - [13/Jan/2023:10:17:28 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
72.38.12.208 - - [13/Jan/2023:10:17:49 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?reply=tr-43850-7444" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76"
108.221.39.97 - - [13/Jan/2023:10:17:58 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
24.45.242.118 - - [13/Jan/2023:10:20:41 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
24.45.242.118 - - [13/Jan/2023:10:21:10 -0600] "POST /ajax/set-var.php HTTP/2.0" 200 21 "https://www.rephunter.net/track-relationships.php?filter=clear" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"</pre>
<p>编辑3:</p>
<p>我们有一个候选解决方案,其灵感来自 @ibrahim 对下面 Lajos Arpad 答案的评论。简而言之,向 ajax 调用添加重试功能,如 https://forum.framework7.io/t/app-request-what-is-the-best-way-to-retry-an-ajax-request-using 所示-app-request/4759,它似乎基于What's the best way to retry an AJAX request on failure using jQuery?。</p>
<p>在我们确认此修复有效后(这将需要一些“没有报告错误”的时间),我会将其标记为“答案”,@ibramim 是否应该发布他关于重试的评论作为答案。</p>