0

这是一个javascript函数:

  function getValue(key) {
    var value;
    switch(_options.myType){
      case "cookie":
        value = readFromCookie(key);
        break;
      case "localStorage":
        value = readFromLocalStorage(key);
        break;
      case "db":
        //return value from the server
        // how do I wait for the result?
        $.ajax({
            type: "GET",
            url: "123",
            data: { .... },
            success: function(data){
               value = data; 
            }
        });
        break;
    }
    return value;
  };

在发送ajax请求的情况下,我需要等到ajax请求完成。我该怎么做?

并不是说我不能在没有计算值的情况下离开函数。这意味着我不能在success:处理程序中放置一个函数,该函数稍后会返回该值(或者我可能不明白什么?)。所以必须在函数内计算getValue()

更新

PS那么如何重构我的代码以便能够在success:处理程序中使用回调呢?这是代码的第二部分:

MyClass123.prototype.myMethod = function(value) {
      //..............
      var var1 = this.getValue("key1");
      if (var1 == "123") { ... }
      else { .... }
      //..............
    }
  };
4

3 回答 3

8

请看下面的后续

可以使 ajax 请求同步,但这通常是个坏主意(而且 jQuery 将不再支持它)。

相反,请getValue接受回调:

function getValue(key, callback) {
   switch(_options.myType){
     case "cookie":
       setTimeout(function() {
           callback(readFromCookie(key));
       }, 0);
       break;
     case "localStorage":
       setTimeout(function() {
           callback(readFromLocalStorage(key));
       }, 0);
       break;
     case "db":
       //return value from the server
       // how do I wait for the result?
       $.ajax({
           type: "GET",
           url: "123",
           data: { .... },
           success: function(data){
              callback(data);
           }
       });
       break;
   }
}

请注意,我使用setTimeout的是readFromCookiereadFromLocalStorage回调。为什么?因为如果getValue 可能异步返回它的值,它应该总是这样做。使用超时0要求浏览器在控制权返回给浏览器后尽快执行此操作(尽管它通常限制在不少于 5-10 毫秒)。


在下面回复您的评论:

你读过我写的吗?我说因为某种原因我做不到。

我错过了那一点,但恕我直言,你可以。它可能需要对代码进行一些重构,但您可以这样做,而且应该这样做。这就是现代 Web 应用程序的工作方式。如果您的结构不支持它,则需要修复结构。您可以async: false将请求用作临时解决方法,直到您可以正确执行为止。(嘿,我们都去过那里,不得不做这样的事情。)请注意,它计划在不久之后退役(只是 jQuery 对它的支持,您仍然可以直接使用 XHR 来执行同步请求)。


关于您更新的问题,这是您更新该代码的方式:

MyClass123.prototype.myMethod = function(value) {
  this.getState("key1", function(var1) {
    //                           ^--- Note the var becomes an arg
    if var1 == "123"{ ... }
    else { .... }
  });
};

请注意它实际上变化很小。用于跟随调用的逻辑getState改为进入您传递给它的回调。

于 2013-01-27T12:36:51.450 回答
2

您可以通过指定async: false-使 AJAX 请求同步,虽然不推荐,但可以这样做。如果绝对是在getValue()AJAX 请求返回之前您的函数不应该返回的情况,那么async就是要走的路。

$.ajax({
    type: "GET",
    url: "123",
    async: false // NEW
    data: { .... },
    success: function(data){
        value = data; 
    }
});

替代使用thenand when

function getValue(key, callback) {
   switch(_options.myType){

     ...

     case "db":
       return $.ajax({ // note the 'return'
           type: "GET",
           url: "123",
           ...
       });
   }
}

在你称之为的地方,称之为:

$.when(getValue()).then(function() {
   // do the rest here ...
});
于 2013-01-27T12:36:12.267 回答
2

正确的做法是重构您的程序流程,以便您可以将逻辑放置在success处理程序中。

您可以使用该async选项使 Ajax 请求同步,但这很愚蠢。它会减慢您的应用程序,因为浏览器窗口会冻结,直到请求成功返回(或超时)。它在 JavaScript 开发中并不经常使用,这是有充分理由的。

于 2013-01-27T12:36:27.867 回答