jQuery - 回调无效

jQuery - callback not working

我有以下 json return 来自 api 电话。我想检查是否为某些产品记录了特定类型的事件,如果它是真的 return 一条适当的消息并退出点击处理程序,否则继续。我有一个名为 hasEvent 的函数来执行此检查。但是,当我从 someOtherFunction 调用此函数时,即使检查为真,也不会 return 编辑任何消息?

{
  "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 函数添加了回调,但现在如果显示警报,我该如何退出以下点击处理程序。以下只是继续执行,直到点击处理程序内的所有操作都完成,这不是我想要的 - 如果显示事件和警报,我想退出处理程序:

$('.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;
}

您的代码中的问题是 $.getJSON 是异步的,这意味着当您执行它时,它正在启动一个操作,该操作不会在下一行代码 运行 之前完成。当它完成时,您传递给 .done 的回调将执行,但到那时,您的大部分其他代码将已经 运行。这意味着当您调用 hasEvents 时,您正在将 msg 初始化为 undefined,然后向 getEvents 传递一个回调,该回调将在您的 ajax 调用到来时调用背部。但是,由于该回调不会立即执行,因此 hasEvents 继续 returns msg,它仍然等于 undefined,这是 Javascript。这意味着即使您的 ajax 调用返回并执行回调,hasEvent(productType) 也已经评估为 false。

一个可能的解决方案是给 hasEvent 第二个参数,这是一个回调。然后在您的 _.find 中,您可以使用消息而不是 return 执行该回调,如下所示:

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 函数 return 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);
      });
  }
}