简体   繁体   English

等待直到ajax请求完成

[英]Wait until ajax request has been completed

Here is a javascript function: 这是一个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;
  };

In case of sending ajax request, I need to wait untill the ajax request has been completed. 在发送ajax请求的情况下,我需要等待直到ajax请求已完成。 How can I do it? 我该怎么做?

Not that I can't leave the function without having the value calculated. 并不是说我不能在没有计算值的情况下离开函数。 Which means that I can't place a function inside success: handler which will return the value later (or perhaps I don't understand something?). 这意味着我无法将函数放置在success:内部success:处理程序将在以后返回值(或者我可能不明白?)。 So it must be calculated within the function getValue() . 因此,必须在函数getValue()进行计算。

UPDATE 更新

PS So how do refactor my code to be able to use callback inside success: handler? PS那么如何重构我的代码以能够在success:内部使用回调函数success:处理程序? Here is the second part of the code: 这是代码的第二部分:

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

See follow-up below 请参阅下面的后续内容

You could make the ajax request synchronous, but that's generally a bad idea (and jQuery won't support it much longer). 可以使ajax请求同步,但这通常不是一个好主意(jQuery将不再支持它更长的时间)。

Instead, make getValue accept a callback: 相反,使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;
   }
}

Note that I'm using setTimeout for the readFromCookie and readFromLocalStorage callbacks. 请注意,我正在将setTimeout用于readFromCookiereadFromLocalStorage回调。 Why? 为什么? Because if getValue might return its value asynchronously, it should always do so. 因为如果getValue 可能异步返回其值,则应该始终这样做。 using a timeout of 0 asks the browser to do it as soon as possible once control yields back to the browser (although it's usually clamped to no less than 5-10ms). 使用超时值为0 ,一旦控件将控制权交还给浏览器,浏览器应尽快执行此操作(尽管通常将其限制为不少于5到10毫秒)。


Re your comment below: 在下面重新发表您的评论:

Have you read what I write? 你读我写的东西了吗? I said that I can't do it for some reason. 我说由于某些原因我做不到。

I missed that bit, but with all due respect, you can . 我错过了这一点,但是在所有应得的尊重下,您可以 It may require some refactoring of code, but you can do it, and should. 它可能需要对代码进行一些重构,但是您可以并且应该这样做。 This is how modern web applications work. 这就是现代Web应用程序的工作方式。 If your structure doesn't support it, you need to fix the structure. 如果您的结构不支持该结构,则需要修复该结构。 You can use async: false on the request as a temporary workaround until you can do it properly. 您可以对请求使用async: false作为临时解决方法,直到可以正确执行为止。 (Hey, we've all been there and had to do things like that.) Note that it's scheduled for retirement before too long (just jQuery's support of it, you'll still be able to use XHR directly to do synchronous requests). (嘿,我们都去过那里,必须做类似的事情。)请注意,它计划在很长的时间内退休(只是jQuery的支持,您仍然可以直接使用XHR进行同步请求)。


Re your updated question, here's how you update that code: 重新输入更新的问题,以下是更新代码的方法:

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

Note how little it actually changes. 请注意它实际变化的幅度。 The logic that used to follow the call to getState instead goes into the callback you pass into it. 相反,用于跟随 getState调用的逻辑进入了传递给它的回调。

You can make the AJAX request synchronous by specifying async: false - which is not recommended but possible. 您可以通过指定async: false来使AJAX请求同步async: false 不建议这样做,但可以这样做。 If it absolutely is the case that your getValue() function should not return before the AJAX request returns, then async is the way to go. 如果绝对是在AJAX请求返回之前您的getValue()函数不应该返回的情况,那么使用asyncasync的方法。

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

Alternative using then and when : thenwhen使用替代方法:

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

     ...

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

and where you call it, call it like: 以及在何处调用它的方式如下:

$.when(getValue()).then(function() {
   // do the rest here ...
});

The right thing to do is to restructure your program flow so you can place your logic in the success handler. 正确的做法是重组程序流,以便可以将逻辑放入success处理程序中。

You can make Ajax requests synchronous by using the async option, but that is silly. 您可以使用async选项使Ajax请求同步,但这很愚蠢。 It'll slow down your app, because the browser window freezes until the request comes back successful (or times out). 这会降低应用程序的速度,因为浏览器窗口会冻结,直到请求成功返回(或超时)为止。 It's not often used in JavaScript development and for good reason. 有充分的理由,它不经常在JavaScript开发中使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM