我的问题基本上是我试图创建一个通用的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
答案 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)
感谢所有帮助我回答这个问题的人!所有给出的答案都包含有用的相关信息以帮助回答这个问题,但是,由于没有人回复包含我解决问题所需的全部理解,所以我发布了答案。
解决方案如下:
回调函数只应在XHR请求完成后执行。
- 这对于我们使用异步AJAX这一事实尤为重要。
我需要确保将ALAMI.Hangman.Wordlist
设置为等于适当的值ajaxResponse
,而不是ALAMI.XHR.Get()
。
我提出的代码如下。
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');
});