[编辑]关于回调的新问题[编辑]
我正在尝试使用Ajax和Javascript加载一些本地文本文件,但我无法使回调正常工作。 我概述了我的代码:
PATH=/Users/Tim/.opam/system/bin:/Library/Frameworks/Python.framework/Versions/3.2/bin:/opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/local/bin:/usr/local/bin
OCAML_TOPLEVEL_PATH=/Users/Tim/.opam/system/lib/toplevel
PERL5LIB=/Users/Tim/.opam/system/lib/perl5:
MANPATH=/Users/Tim/.opam/system/man:/opt/local/share/man:
OPAMSWITCH=system
OPAMUTF8MSGS=1
CAML_LD_LIBRARY_PATH=/Users/Tim/.opam/system/lib/stublibs:/usr/local/lib/ocaml/stublibs
SHELL=/bin/bash
TERM=dumb
TMPDIR=/var/folders/kv/kmn525v16kb2mz2hrhq3q4mh0000gn/T/
BASHRC_HAS_BEEN_RUN=1
Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.8tP8Ej926f/Render
EMACSDATA=/Applications/Emacs.app/Contents/Resources/etc
OLDPWD=/Users/Tim/Documents/Work/Code
EMACSPATH=/Applications/Emacs.app/Contents/MacOS/bin
USER=Tim
EMACS=t
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.EXKwsf0Dz0/Listeners
TERMCAP=
__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x0
COLUMNS=190
BASH_PROFILE_HAS_BEEN_RUN=1
PWD=/Users/Tim/Documents/Work/Code/OCaml with graphics
XPC_FLAGS=0x0
XPC_SERVICE_NAME=0
EMACSLOADPATH=/Applications/Emacs.app/Contents/Resources/site-lisp:/Applications/Emacs.app/Contents/Resources/lisp:/Applications/Emacs.app/Contents/Resources/leim
SHLVL=1
HOME=/Users/Tim
LOGNAME=Tim
INFOPATH=/Applications/Emacs.app/Contents/Resources/info:
DISPLAY=/private/tmp/com.apple.launchd.jPYPDR7RIj/org.macosforge.xquartz:0
INSIDE_EMACS=23.1.1,comint
EMACSDOC=/Applications/Emacs.app/Contents/Resources/etc
_=/usr/local/bin/opam
OPAM_PACKAGE_VERSION=1.0
OPAM_PACKAGE_NAME=graphics
MAKELEVEL=
MAKEFLAGS=
本地存储的是文件one.txt,two.txt,three.txt等... 即使for循环为文件中的每个键调用open(),回调也只执行一次。仅填充文件(七)中的最后一项。 我不明白为什么。
UPDATE 在提供@xianshenglu的答案后,我发现实际上不需要回调。这也适用
var theFiles = {
one: null,
two: null,
three: null,
four: null,
five: null,
six: null,
seven: null
};
function callback(pos,arrayofwords) {
theFiles[pos]=arrayofwords;
}
xhr = new XMLHttpRequest();
var getFiles = function(theFiles,callback) {
for (var p in theFiles) {
console.log("in getFile: " + p);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
callback(p,xhr.responseText.split(/\r?\n/));
}
};
xhr.open("GET", p + ".txt", true);
xhr.send();
}
}
答案 0 :(得分:0)
试试这个:
var getFiles = function(theFiles, callback) {
for (let p in theFiles) {
let xhr = new XMLHttpRequest();
console.log("in getFile: " + p);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);//test if work;
callback(p, xhr.responseText.split(/\r?\n/));
}
};
xhr.open("GET", p + ".txt", true);
xhr.send();
}
};
说明:
如果您使用一个忙于发送和接收的xhr对象并告诉它发送另一个请求,它只会停止执行任何操作并发出新请求。
关于var的另一种解释:
function f(a) {
console.log(a);
}
for (var i = 0; i < 3; i++) {
document.body.onclick = function() {
f(i)
};
}
html,
body {
width: 100%;
height: 100%;
}
单击body三次,总是得到3,最后一个值;所以,不要使用var in循环,因为上面的代码几乎等于:
function f(a) {
console.log(a);
}
var i;
for (i = 0; i < 3; i++) {
document.body.onclick = function() {
f(i);// not execute at once,when executing ,i already becomes the last one,which is 3;
};
}
了解更多信息,做一些关于var hoisting的研究,你会得到很多,MDN
答案 1 :(得分:0)
另一种解决方案,使用async / await和fetch。
let getFile = async (p) => {
console.log("in getFile: " + p);
let res = await fetch('/' + p + '.txt');
let text = await res.text();
return text.split(/\r?\n/);
}
let getFiles = async () => {
for (let p in theFiles) theFiles[p] = await getFile(p);
}
getFiles();
的更多信息
答案 2 :(得分:0)
您应该使用let
代替var
。
如果您使用让而不是 var ,它将会起作用,因为:
for
循环非常快(运行ajax之前)所以如果你使用var
for (var p in theFiles)
,p
值将在每个值中覆盖 迭代循环,最后填充最后一个值theFiles
,现在将启动ajax操作,所有操作都使用p
和p
已填充theFiles
的最后一项。但如果我们使用让代替var,则每个
p
会有所不同 在循环的迭代中比另一个p
。所以效果很好。