我有一个我正在处理的项目库存跟踪系统,我似乎遇到了状态正确更新的问题。
这里是JS,从我可以告诉我在$.each
循环中存在的对象的值,当ajax函数success/error/complete
被用于像我注入HTML的地方。
(function() {
function realtime() {
// Realtime Elements...
$('.realtime').each(function() {
// Self Reference
var objThis = $(this);
// Realtime Items...
if(objThis.hasClass('foxyinv-item')) {
// Item Code to Check
var valCode = objThis.find('[name=code]').val();
// Status Element
var objStock = objThis.find('div.stock');
// Begin AJAX Overlap Prevention
objThis.removeClass('realtime');
$.ajax({
url: 'checkstock.php',
type: 'post',
data: {
session: FC.session_id,
code: valCode,
qty: 1
},
success: function(data) {
var response = data.split(':');
switch(response[0]) {
case 'ok':
console.log(valCode+' can be sold, it is '+response[1]);
objStock.html(valCode+'<button type="submit">Add to Cart</button>'+response[1]);
break;
case 'no':
console.log(valCode+' cannot be sold, it is '+response[1]);
objStock.html(response[1]);
break;
default:
objStock.html('<span class="error">Error!</span>');
break;
}
},
error: function() {
console.log('checkstock.php error!');
objStock.html('<span class="error">Error!</span>');
},
complete: function() {
// End AJAX Overlap Prevention
objThis.addClass('realtime');
}
}); // $.ajax()
}
}); // $('.realtime').each()
} // realtime()
// Document Ready...
$(document).on('ready', function() {
// Main Loop...
var RTI = setInterval(function() { realtime() }, 5000);
realtime();
});
})();
这是显示产品的页面上的代码片段
// Items
$items = '';
$result = mysqli_query($mysqli, "SELECT * FROM foxyinv_items");
if($result && mysqli_num_rows($result) > 0) {
while($assoc = mysqli_fetch_assoc($result)) {
$items .=
'<div class="foxyinv-item realtime">'.
'<form action="https://mlkart.foxycart.com/cart" method="post" accept-charset="utf-8">'.
'<input type="hidden" name="name" value="'.$assoc['item_name'].'" />'.
'<input type="hidden" name="code" value="'.$assoc['item_code'].'" />'.
'<input type="hidden" name="price" value="'.$assoc['item_price'].'" />'.
'<div class="name">'.$assoc['item_name'].'</div>'.
'<div class="code">'.$assoc['item_code'].'</div>'.
'<div class="price">'.$assoc['item_price'].'</div>'.
'<div class="stock">Checking...</stock>'.
'</form>'.
'</div>';
}
mysqli_free_result($result);
}
回调脚本运行正常,但例如它将返回这些类型的响应:
ok:
(可以添加,无状态)
ok:In Stock
(可以添加状态)
no:Out of Stock
(无法添加状态)
error
(mgmt面板中存在错误)
最简单的问题是,如何确保javascript变量objThis
,valCode
和objStock
与ajax调用时保持一致制作?我将研究同步进行ajax调用的可能性,但我不喜欢它会在调用完成之前挂起页面的含义,因此同步调用不是可接受的解决方案。
修改
使用jfriend并按照建议评论所有内容,控制台指示范围正在维护,但是当引用.html(code)
时,它将被发送到错误的对象。这是控制台日志:
1: start
1: inside hasClass'foxyinv-item'
1: about to call ajax, valCode=EX-02
1: objThis.data(code)=EX-02
1: success: valCode=EX-02
1: success: data=ok:In Stock
1: EX-02 can be sold, it is In Stock
1: objThis.data(code)=EX-02
1: ajax complete
1: objThis.data(code)=EX-02
2: start
2: inside hasClass'foxyinv-item'
2: about to call ajax, valCode=EX-01
2: objThis.data(code)=EX-01
2: success: valCode=EX-01
2: success: data=error
2: EX-01 cannot be sold, it has an error!
2: objThis.data(code)=EX-01
2: ajax complete
2: objThis.data(code)=EX-01
这变得越来越奇怪了......
解决方案:
好吧,所以我觉得自己像一个完全白痴,我很惊讶没有人接受它...在我的项目显示脚本中我非常巧妙地使用'<div class="stock">Checking...</stock>'
。我修好了它,实际上是</div>
。
很抱歉浪费了你这么多时间的朋友。然而,你确实让我开始了正确的道路,因为我发现范围正在维持,它必须在另一个涉及的文件中。我希望我能早点接受它!深夜和清晨正在迎头赶上!
答案 0 :(得分:0)
.each()
回调中的任何变量的值(如objThis
,valCode
和objStock
都在闭包中,并且会为每个单独的ajax回调函数保留其值。这是使用带有回调函数的.each()
与使用没有内置闭包的for
循环的优点之一。
现在,如果在ajax调用完成之前随时修改了这些变量所指向的基础数据,那么你仍然会遇到问题,解决这个问题的唯一方法就是停止修改你不知道的数据。我想更改或制作该数据的本地副本,以免任何人弄乱您的副本(在这种情况下,这看起来不像是一个问题)。
为了追踪究竟发生了什么,我建议如下:
在全球范围内声明:
var transactionId = 0;
然后,使用console.log()
这样的语句检测代码:
(function() {
function realtime() {
// Realtime Elements...
$('.realtime').each(function() {
var localId = ++transactionId;
console.log(localId + ": start");
// Self Reference
var objThis = $(this);
// Realtime Items...
if(objThis.hasClass('foxyinv-item')) {
console.log(localId + ": inside hasClass'foxyinv-item'");
// Item Code to Check
var valCode = objThis.find('[name=code]').val();
// Status Element
var objStock = objThis.find('div.stock');
// Begin AJAX Overlap Prevention
objThis.removeClass('realtime');
console.log(localId + ": about to call Ajax, valCode=" + valCode);
$.ajax({
url: 'checkstock.php',
type: 'post',
data: {
session: FC.session_id,
code: valCode,
qty: 1
},
success: function(data) {
console.log(localId + ": success: valCode=" + valCode);
console.log(localId + ": success: data=" + data);
var response = data.split(':');
console.log(localId + ": success: response=" + response);
switch(response[0]) {
case 'ok':
console.log(valCode+' can be sold, it is '+response[1]);
objStock.html(valCode+'<button type="submit">Add to Cart</button>'+response[1]);
break;
case 'no':
console.log(valCode+' cannot be sold, it is '+response[1]);
objStock.html(response[1]);
break;
default:
objStock.html('<span class="error">Error!</span>');
break;
}
},
error: function() {
console.log(localId + ": ajax error");
console.log('checkstock.php error!');
objStock.html('<span class="error">Error!</span>');
},
complete: function() {
console.log(localId + ": ajax complete");
// End AJAX Overlap Prevention
objThis.addClass('realtime');
}
}); // $.ajax()
}
}); // $('.realtime').each()
} // realtime()
// Document Ready...
$(document).on('ready', function() {
// Main Loop...
var RTI = setInterval(function() { realtime() }, 5000);
realtime();
});
})();
注意:正如您已经猜测的那样,您不应该切换到同步ajax。这不是编码或解决您可能遇到的任何问题的正确方法。