如何从XHR函数中转义已解析的数据?

时间:2012-02-25 08:21:24

标签: javascript ajax xmlhttprequest

我的问题基本上是我试图创建一个通用的Ajax函数,仅用于检索将被解析的信息,然后自动存储为任何调用它的值。在这个特定情况下,它是我正在制作的刽子手游戏的巨型词典单词列表。如何将ajaxRequest.responseText.split("\n")创建的数组转义为任何调用它。在我的情况下,它将是ALAMI.Hangman.Wordlist

我的最终目标是能够使用ALAMI.Hangman.Wordlist[i]并让它返回存储在数组中该位置的任何字符串的值。

在您发现这不是我的所有代码之前,XHR请求函数是通过ALAMI.XHR();调用的,如下所示,但我没有将其包含在此代码中,因为我认为这是不必要的。

ALAMI.XHR.Get = function(URL){
  "use strict";
  var ajaxRequest = ALAMI.XHR();
  var ajaxResponse;

  ajaxRequest.open("GET", URL, true);
  ajaxRequest.send(null);
  ajaxRequest.onreadystatechange = function(){
    if(ajaxRequest.readyState === 4){
      ajaxResponse = ajaxRequest.responseText.split("\n");
      var extensionLocation = URL.lastIndexOf('.');
      console.log(URL.substr(extensionLocation) + " file ...... " + ajaxResponse.length + " lines.");
    }
  }
  return ajaxResponse;
}

ALAMI.Hangman = ALAMI.Hangman || {};

ALAMI.Hangman.Wordlist = ALAMI.XHR.Get('fulldictionary.txt');

//I want ALAMI.Hangman.Wordlist to be equal to the Array of ajaxRequest.responseText.split("\n")

我的最终目标是能够使用ALAMI.Hangman.Wordlist[i]并让它返回存储在数组中该位置的任何字符串的值。

此外,我正在尝试使我的ajax函数成为一种可以无限次使用的通用方法。例如:

 ALAMI.Hangman.Wordlist1 = ALAMI.XHR.Get('fulldictionary.txt');
 ALAMI.Hangman.Wordlist2 = ALAMI.XHR.Get('dictionary2.txt');

最终目标是:

如果在全局空间中我写console.log(ALAMI.Hangman.Wordlist[0]);它当前显示为未定义,但是,我想要的是将数组存储在ALAMI.Hangman.Wordlist中,这样当我这样做时它会输出数组的第一个值。

console.log(ALAMI.Hangman.Wordlist[0]); //Should output Apple

4 个答案:

答案 0 :(得分:1)

[根据评论进行编辑]

如果您想从XHR请求的结果中填充ALAMI.Hangman.Wordlist,您应该在该请求的回调中执行此操作

ALAMI.Hangman = ALAMI.Hangman || {};

//change ALAMI.XHR.Get = function(URL) to
//       ALAMI.XHR.Get = function(URL,listID)

ALAMI.XHR.Get('fulldictionary.txt','WordList');
ALAMI.XHR.Get('fulldictionary2.txt','WordList2');
ALAMI.XHR.Get('fulldictionary3.txt','WordList3');

// [...]
  ajaxRequest.onreadystatechange = function(){
    if(ajaxRequest.readyState === 4){
      ajaxResponse = ajaxRequest.responseText.split("\n");
      var extensionLocation = URL.lastIndexOf('.');
      ALAMI.Hangman[listID]  = ajaxResponse; // <===
      // [...]
      // do stuff with the populated ALAMI.Hangman[listID]
    }
  }

答案 1 :(得分:1)

所以你想创建一个WordList对象,然后将其传递给你的程序的其余部分,而不必在访问WordList之前调用ajax请求?

你遇到了问题,因为没有使用回调,你的代码的其余部分在AJAX请求完成之前就试图评估WordList,事实上即使resquest已经填满,浏览器也在等待你当前的'循环'代码在执行readystatechange回调以填充列表之前完成。您可以使用同步AJAX调用,或者我可能会通过以下方式重写您的XHR函数:

function wordlist(url,withwords) {
    var xhr = // create your xhr object;
    xhr.onload = function (data) {
        withwords(parsetolist(data));
    }
    xhr.send()
}

wordlist('dict1.txt', function(words) {
    // pass words around to other functions
    filterwords(words);
    randomizewords(words);
    // or use it here
    console.log(words[2]);
}

如果你真的想将单词列表设置为全局,那么其他程序可以在外面使用它 然后你必须将wordlist更改为一个函数,该函数在每次使用时都会进行回调...不是很漂亮。至少那样你可以更懒惰地评估

function wordlist2(url) {
    var evaluated = false;
    var response = function (index, withword) {
        if ( evaluated ) { withword(evaluated[index]); }
        else {
            wordlist(url, function(words) {
                 evaluated = words;
                 withword(words[index]);
            })
        }
    }
    return response;
}
ALAMI.WORDLIST = wordlist2('dict1.txt');
ALAMI.WORDLIST(2,function (word) { console.log(word); });

答案 2 :(得分:1)

您使用XMLHttpRequest()对象的方式存在问题。因为您在true中指定了ajaxRequest.open("GET", URL, true);,所以您实际上要求在异步线程中完成请求,以便主线程不会被阻止。这是HTML应用程序的好设计,但它需要您更好地理解如何更好地处理结果,请采用以下示例:

<html>
<head>
<title>ALAMI Test</title>
<script language="JavaScript">
function doit(URL) {
  console.log('mainthread - doit begin');
  var ajaxRequest = new XMLHttpRequest();
  ajaxRequest.open("GET", URL, true);
  ajaxRequest.onreadystatechange = function() {
    if (ajaxRequest.readyState === 4) {
      console.log('asyncthread - readystatechange begin');
      var ajaxResponse = ajaxRequest.responseText.split("\n");
      var extensionLocation = URL.lastIndexOf('.');
      console.log('asyncthread - readystatechange end');
    }
  }
  console.log('mainthread - ajaxRequest.send');
  ajaxRequest.send(null);
  console.log('manthread - doit end');
}
</script>
</head>
<body>
<input type="button" value="doit" onclick="doit('http://localhost/fulldictionary.txt')"/>
</body>

请注意我标记为console.log的位置以及主线程中的位置以及 asyncthread 中的位置。如果您要运行该脚本,您应该会在控制台中看到以下文本:

LOG: mainthread - doit begin 
LOG: mainthread - ajaxRequest.send 
LOG: manthread - doit end 
LOG: asyncthread - readystatechange begin 
LOG: asyncthread - readystatechange end 

你编写脚本的方式,你假设结果同步发生,即

LOG: mainthread - doit begin 
LOG: mainthread - ajaxRequest.send 
LOG: asyncthread - readystatechange begin 
LOG: asyncthread - readystatechange end 
LOG: manthread - doit end 

这就是您的脚本不起作用的原因。正确的设计是继续使用异步线程,但使用它来“回发”它找回的ALAMI对象的记录。因此,您不能使用以下代码行:

ALAMI.Hangman.Wordlist = ALAMI.XHR.Get('fulldictionary.txt');

因为当mainthread完成时,wordlist仍然是未知的,相反,你必须重写它:

ALAMI.XHR.Get('fulldictionary.txt');

在你的asyncthread实现中,你必须填充你的Wordlist。

即。需要进行一些重新设计。

答案 3 :(得分:0)

感谢所有帮助我回答这个问题的人!所有给出的答案都包含有用的相关信息以帮助回答这个问题,但是,由于没有人回复包含我解决问题所需的全部理解,所以我发布了答案。

解决方案如下:

  1. 我需要使用callback function
  2. 回调函数只应在XHR请求完成后执行。

    - 这对于我们使用异步AJAX这一事实尤为重要。

  3. 我需要确保将ALAMI.Hangman.Wordlist设置为等于适当的值ajaxResponse,而不是ALAMI.XHR.Get()

  4. 我提出的代码如下。

    ALAMI.XHR.Get = function(URL, callback){ //callback argument was added
      "use strict";
      var ajaxRequest = ALAMI.XHR();
      var ajaxResponse;
    
      ajaxRequest.open("GET", URL, true);
      ajaxRequest.send(null);
      ajaxRequest.onreadystatechange = function(){
        if(ajaxRequest.readyState === 4){
          ajaxResponse = ajaxRequest.responseText.split("\n");
          var extensionLocation = URL.lastIndexOf('.');
          console.log(URL.substr(extensionLocation) + " file, " + ajaxResponse.length + " lines");
          if(callback){
            callback(ajaxResponse); //callback is called after URL is parsed into an Array
          }
        }
      }
    }
    
    ALAMI.Hangman = ALAMI.Hangman || {};
    ALAMI.Hangman.Wordlist;
    
    ALAMI.XHR.Get('fulldictionary.txt', function(aR){ //callback function is specified
      ALAMI.Hangman.Wordlist = aR;                    //assigning the Wordlist property now works!
      console.log('Wordlist Retrieved');
    });