Ajax回调仅在最后一次循环迭代时调用一次

时间:2018-02-10 01:36:32

标签: javascript ajax callback

[编辑]关于回调的新问题[编辑]

我正在尝试使用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();
  }
}

3 个答案:

答案 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();

有关fetchasync / await

的更多信息

答案 2 :(得分:0)

您应该使用let代替var

  

如果您使用而不是 var ,它将会起作用,因为:

     

for循环非常快(运行ajax之前)所以如果你使用var   for (var p in theFiles)p值将在每个值中覆盖   迭代循环,最后填充最后一个值   theFiles,现在将启动ajax操作,所有操作都使用pp   已填充theFiles的最后一项。

     

如果我们使用代替var,则每个p会有所不同   在循环的迭代中比另一个p。所以效果很好。