2016-09-01 11 views
2

我有一个文件,tst.html与内容:JavaScript(Vanilla,no jQuery) - 具有* synchronous的函数* AJAX(XMLHttpRequest)调用的行为与async相同?

part two 

(无标记或其他任何东西,只是为了演示)

,然后加载所述文件,通过同步 AJAX( XMLHttpRequest):

function someFunc() { 
    var str = 'part one_'; 

    var x = new XMLHttpRequest(); 
    x.open('GET', 'tst.html', false); // "false" for synchronous 
    x.onreadystatechange = function() { 
     if(x.readyState === 4) { 
      switch(x.status) { 
       case 200: 
        str += x.responseText.trim(); 
        break; 

       default: 
        return ''; // Or something 
        break; 
      } 
     } 
    } 
    x.send(); 

    str += '_part three'; 

    return str; 
} 

调用好玩ction:

alert(someFunc()); 

// Returns "part one_part two_part three" 

这是所需的行为。

但如果我把AJAX调用到它自己的功能:

function ajaxCall() { 
    var x = new XMLHttpRequest(); 
    x.open('GET', 'tst.html', false); 
    x.onreadystatechange = function() { 
     if(x.readyState === 4) { 
      switch(x.status) { 
       case 200: 
        return x.responseText.trim(); 
        break; 

       default: 
        return ''; 
        break; 
      } 
     } 
    } 

    x.send(); 
} 

function someFunc() { 
    var str = 'part one'; 

    str += ajaxCall(); 

    str += 'part three'; 

    return str; 
} 

然后调用它:

alert(someFunc()); 

// Returns "part one_undefined_part three" 

函数返回联军字符串AJAX有机会完成之前,这与其异步表兄弟的行为相同。

我一直在寻找沿着“同步AJAX功能”的东西,但是没有任何东西可以用于任何用途。

AJAX调用的最终用例位于函数的递归集合内部,其进一步处理依赖于AJAX返回。类似:

function one(url) { 
    var x = new XMLHttpRequest(); 
    x.open('GET', url, false); 
    x.onreadystatechange = function() { 
     return two(x.responseText.trim()); 
    } 
    x.send(); 
} 

function two(str) { 
    var output; 

    output += stuff; 

    // ... parse through str 
    // ... until match found 

    if(isURL(match)) {      // If `match` is a URL 
     output += one(match); 
    }else if(isFormattedString(match)) { // if `match` is a string 
     output += two(match); 
    } 

    output += more stuff; 

    // More processing of output  

    return output; 
} 

var final = one(url); 

在上面的例子:

  • 系统总是与URL启动(one(url)
  • one()返回一个字符串,其本身为two(str)
  • 开口参数
  • two()内,解析器可能遇到以下任一种:

    1. 另一个URL或

    2. 一个可解析的字符串。

  • 取决于哪个是,两个功能中的一个被称为

  • 的输出被添加到系统中的最终结果

one()从一个回调将不起作用在这一点上,因为我仍然需要在two()之内有最后的return

function one(url, callback) { 
    // ... AJAX stuff 
    { 
     callback(two(x.responseText)); 
    } 
} 

function two(str) { 
    // ... same as previous 

    // The following doesn't work, because then `two()` no longer has a `return` 
    // ... and any other code (i.e. for !isURL cases) will still continue to execute 
    if(isURL(match)) { 
     one(match, function(result) { 
      output += result; 

      // ... more processing 

      return output; 
     }); 
    }else if(...) { 
     // ... same as previous 
    } 

    // ... more stuffs 
} 

我发现的唯一的另一件事是deferred,但我不能确定它如何与这个工作,要么。

有没有一种方法可以强制JavaScript像对待其他同步函数一样对待它,其中执行代码会停止,直到函数完成为止?我不清楚它为什么还没有,AJAX请求特别声明为异步。

在此先感谢。

+3

你的函数'ajaxCall'不返回任何东西 - 相当于'return undefined' - 你需要从函数返回一些东西(不是onreadystate回调) –

+0

同步ajax调用真的不是一个好主意 - 如果服务器有问题会怎样? JavaScript线程将等待直到服务器响应,并且页面将完全不响应用户。同步ajax永远不会有好的例子。不要使用它。 – Simba

+0

我会建议尝试使用“承诺”(整洁的东西)。在Jamiec的回答中发布的链接中给出了一个简要的解释,否则在MDN中查看:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise – Winter

回答

6

我喜欢你的长,具体的问题(!希望大家把尽可能多的精力投入到问),但在本质上它归结为:

function ajaxCall() { 
    var x = new XMLHttpRequest(); 
    x.open('GET', 'tst.html', false); 
    x.onreadystatechange = function() { 
     if(x.readyState === 4) { 
      switch(x.status) { 
       case 200: 
        return x.responseText.trim(); 
        break; 

       default: 
        return ''; 
        break; 
      } 
     } 
    } 

    x.send(); 
} 

return语句是从onreadystatechange回报,不ajaxCall如你所料。它不同于你的原始版本,因为你的原始文件只是连接字符串。它与将其转移到自己的功能无关。

不使用同步ajax!了解异步函数的工作方式,尤其是How do I return the response from an asynchronous call?

1

的问题是,你从处理程序return

return x.responseText.trim(); 

回报,但不能从ajaxCall功能 - 它没有return语句,所以总是返回undefined