我从api调用返回了以下json。我想检查是否为某些产品记录了特定类型的事件,如果它返回了正确的消息并退出单击处理程序,则继续。我有一个名为hasEvent
的函数来执行此检查。但是当我从someOtherFunction
调用此函数时,即使检查为真,也不会返回任何消息?
{
"item": {
"Event": [
{
"EventType": {
"Description": "New order"
},
"EventSubType": {
"Description": "Awaiting payment"
}
},
{
"EventType": {
"Description": "New order"
},
"EventSubType": {
"Description": "Dispatched"
}
}
],
"Errors": {
"Result": 0,
"Message": ""
},
"RecordCount": 2
}
}
var getEvents = function (callback) {
var orderId = $("#Id").val();
$.getJSON('api/events?id=' + orderId)
.done(function (data) {
callback(data);
}).fail(function (jqXHR, textStatus, err) {
return;
});
}
var hasEvent = function (productType, callback) {
var msg;
getEvents(function (data) {
_.find(data.item.Event, function (event) {
if (event.EventType.Description == 'New order' &&
event.EventSubType.Description == 'Dispatched' &&
productType = 'xyz') {
msg = 'Some message';
return true;
}
if (event.EventType.Description == 'New order' &&
event.EventSubType.Description == 'Awaiting payment' &&
productType = 'xyz') {
msg = 'A different message';
return true;
}
// Check for Some more conditions and return appropriate message
return false;
});
if (msg)
callback(msg);
});
}
var someOtherFunction = function () {
$('.myselector').click(function (e) {
var productType = $(this).attr("data-product-type");
hasEvent(productType, function(msg) {
alert(msg);
// exit click event handler
return;
});
// otherwise do some other stuff
return false;
}
}
上述代码有什么问题?
*更新*
我已根据Griffins解决方案通过向hasEvent
函数添加回调来更新代码,但现在如果显示警报,如何退出以下点击处理程序。以下只是继续执行,直到click处理程序中的所有操作都完成,这不是我想要的 - 如果有事件和警报显示,我想退出处理程序:
$('.myselector').click(function (e) {
var productType = $(this).attr("data-product-type");
hasEvent(productType, function(eventMsg) {
alert(msg);
// exit click event handler
return;
});
// Do some other stuff only if no events
return false;
}
答案 0 :(得分:0)
代码中的问题是$.getJSON
是异步的,这意味着当您执行它时,它会启动一个在下一行代码运行之前无法完成的操作。完成后,您传递给.done
的回调将会执行,但在此期间,您的大多数其他代码都已经运行。这意味着当您致电hasEvents
时,您正在初始化msg
至undefined
,然后通过getEvents
将在您的ajax呼叫返回时调用的回调。但是,由于该回调不会立即执行,hasEvents
会继续并返回msg
,这仍然等于undefined
,这是Javascript中的虚假值。这意味着即使您的ajax调用返回并执行回调,hasEvent(productType)
已经评估为false。
一种可能的解决方案是给hasEvent
提供第二个参数,这是一个回调。然后在_.find
中,您可以使用消息执行该回调而不是返回它,如下所示:
var getEvents = function (callback) {
var orderId = $("#Id").val();
$.getJSON('api/events?id=' + orderId)
.done(function (data) {
callback(data);
}).fail(function (jqXHR, textStatus, err) {
return;
});
}
var hasEvent = function (productType, callback) {
var msg = null;
getEvents(function (data) {
_.find(data.item.Event, function (event) {
if (event.EventType.Description == 'New order' &&
event.EventSubType.Description == 'Dispatched' &&
productType = 'xyz') {
msg = 'Some message';
return true;
}
if (event.EventType.Description == 'New order' &&
event.EventSubType.Description == 'Awaiting payment' &&
productType = 'xyz') {
msg = 'A different message';
return true;
}
// Check for Some more conditions and return appropriate message
return false;
});
callback(msg);
});
}
var someOtherFunction = function () {
$('.myselector').click(function (e) {
var productType = $(this).attr("data-product-type");
hasEvent(productType, function(eventMsg) {
if (eventMsg) {
console.log(eventMsg);
alert(eventMsg);
} else {
console.log('there was no event!')
}
})
}
}
或者,异步jquery函数返回promises,所以你可以这样做:
var getEvents = function (callback) {
var orderId = $("#Id").val();
return $.getJSON('api/events?id=' + orderId);
}
var hasEvent = function (productType) {
return getEvents()
.then(function (data) {
var foundEvent = _.find(data.item.Event, function (event) {
if (event.EventType.Description == 'New order' &&
event.EventSubType.Description == 'Dispatched' &&
productType = 'xyz') {
}
// Check for Some more conditions and return appropriate message
return false; // if you don't return, it's undefined, which is a falsy value and has the same effect as returning false in _.find
});
return 'some message';
});
}
var someOtherFunction = function () {
$('.myselector').click(function (e) {
var productType = $(this).attr("data-product-type");
hasEvent(productType)
.then(function(eventMsg) {
console.log(eventMsg);
alert(eventMsg);
});
}
}