这篇文章需要技术复核。如何帮忙。

这篇文章需要文法复核。如何帮忙。

这篇翻译不完整。请帮忙从英语翻译这篇文章

本文将指导您完成AJAX基础知识,并为您提供两个简单的实践示例,帮助您开始使用。

什么是 AJAX?

AJAX代表异步JavaScript和XML。简而言之,它是使用 XMLHttpRequest 对象与服务器端脚本进行通信。它可以发送以及接收各种格式的信息,包括JSON,XML,HTML,甚至文本文件。AJAX最吸引人的特性是,它的“异步”性质,这意味着它可以做所有这一切,而不必刷新页面。这让您可以根据用户事件更新页面的某些部分。

AJAX的两个主要功能允许您执行以下操作:

  • 向服务器发出请求,而不重新加载页面
  • 接收和处理服务器中的数据

步骤 1 – 如何发出HTTP请求

为了使用JavaScript向服务器发出 HTTP 请求,您需要一个提供此功能的类的实例。这就是XMLHttpRequest的由来。这样的类最初是在Internet Explorer中作为一个名为XMLHTTP的ActiveX对象引入的。然后,Mozilla,Safari和其他浏览器,实现一个XMLHttpRequest类,支持Microsoft的原始ActiveX对象的方法和属性。同时微软也实现了XMLHttpRequest。

// Old compatibility code, no longer needed.
if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+ ...
    httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 6 and older
    httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}

// new
const httpRequest = new XMLHttpRequest(); 

注意:为了说明的目的,上面是用于创建XMLHTTP实例的代码的一个简化版本。有关更实际的示例,请参阅本文的步骤3。

接下来,您需要决定在收到服务器对您的请求的响应后您想要做什么。在这个阶段,你只需要告诉HTTP请求对象哪个JavaScript函数将处理响应。这是通过将对象的 onreadystatechange 属性设置为当请求的状态更改时应调用的JavaScript函数的名称,如下所示:

httpRequest.onreadystatechange = nameOfTheFunction;

注意,函数名后面没有括号,没有参数传递,因为你只是给函数赋了一个引用,而不是实际调用它。此外,您可以使用JavaScript技术来动态定义函数(称为“匿名函数”),并定义将立即处理响应的操作,而不是给出函数名称,如下所示:

httpRequest.onreadystatechange = function(){
    // 处理服务器响应
};

接下来,在声明接收到响应后会发生什么,您需要实际提出请求。您需要调用HTTP请求类的open( )send( ) 方法,如下所示:

httpRequest.open('GET', 'http://www.example.org/db.json', true);
httpRequest.send(null);
  • 调用open()的第一个参数是HTTP请求方法 - GET,POST,HEAD或任何其他您要使用的服务器支持的方法。保持方法大写按照HTTP标准;否则某些浏览器(如Firefox)可能不会处理请求。有关可能的HTTP请求方法的更多信息,您可以检查 W3C规范
  • 第二个参数是您请求的网页的网址。作为安全功能,您不能调用第三方网域上的网页。确保在所有网页上使用确切的域名,否则当您调用open()时,您将收到“权限被拒绝”错误。一个常见的陷阱是通过domain.tld访问您的网站,但尝试调用www.domain.tld的网页。如果真的需要向另一个域发送请求,请参阅 HTTP访问控制
  • 可选的第三个参数设置请求是否是异步的。如果为TRUE (默认值),则JavaScript函数的执行将继续,而服务器的响应尚未到达。这就是AJAX中的A.

send( ) 方法的参数可以是任何要发送到服务器的数据,如果POST请求。表单数据应以服务器可以轻松解析的格式发送。这可以作为查询字符串,如:

"name=value&anothername="+encodeURIComponent(myVar)+"&so=on"

或以其他几种格式,包括JSON,SOAP等。

注意,如果你想POST数据,你可能必须设置请求的MIME类型。例如,在对作为查询字符串发送的表单数据调用 send() 之前,请使用以下行:

// setRequestHeader & urlencoded

httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

 

步骤 2 – 处理服务器响应

请记住,当您发送请求时,您提供了用于处理响应的JavaScript函数的名称。

httpRequest.onreadystatechange = nameOfTheFunction;

让我们看看这个函数应该做什么。首先,该函数需要检查请求的状态。如果状态的值为XMLHttpRequest.DONE(计算为4),这意味着已收到完整的服务器响应,您可以继续处理它。

if (httpRequest.readyState === XMLHttpRequest.DONE) {
    // 一切都很好,收到回复
} else {
    // 还没准备好
}

readyState值的完整列表记录在 XMLHTTPRequest.readyState,如下所示:

  • 0 (未初始化)
  • 1 (正在加载)
  • 2 (加载完毕)
  • 3 (交互中)
  • 4 (完成)

(Source)

接下来要检查的是HTTP服务器响应的响应代码。所有可能的代码都列在W3C网站上。在下面的示例中,我们通过检查200 OK响应代码来区分成功或失败的AJAX调用。

if (httpRequest.status === 200) {
    // 完美!
} else {
    // 有一个问题的请求
    //例如响应可能包含404(找不到)
    //或500(内部服务器错误)响应代码
}

现在,在检查请求的状态和响应的HTTP状态代码后,您可以根据需要对服务器发送给您的数据进行任何操作。您有两个选项可以访问该数据:

  • http_request.responseText – 以文本字符串形式返回服务器响应
  • http_request.responseXML – 将响应作为XMLDocument对象返回,您可以使用JavaScript DOM函数遍历

请注意,上述步骤仅在使用异步请求(open()的第三个参数设置为true)时有效。如果使用同步请求,则不需要指定函数,可以在调用send()后立即访问服务器返回的数据,因为脚本将停止并等待服务器应答。

步骤 3 – 一个简单的例子

让我们一起将上面的内容做一遍,并且做一个简单的HTTP请求。我们的js代码会请求一个包含了“I'm a test”文本、名字是test.html的HTML文档,接着我们会调用alert()输出test文件的内容。

注意:这个例子仅仅使用了js(没有涉及到jQuery)。 

  此外,HTML,XML和PHP文件应放置在同一目录中。

<span id="ajaxButton" style="cursor: pointer; text-decoration: underline">
  Make a request
</span>
<script type="text/javascript">
(function() {
  var httpRequest;
  document.getElementById("ajaxButton").onclick = function() { makeRequest('test.html'); };

  function makeRequest(url) {
    httpRequest = new XMLHttpRequest();

    if (!httpRequest) {
      alert('Giving up :( Cannot create an XMLHTTP instance');
      return false;
    }
    httpRequest.onreadystatechange = alertContents;
    httpRequest.open('GET', url);
    httpRequest.send();
  }

  function alertContents() {
    if (httpRequest.readyState === XMLHttpRequest.DONE) {
      if (httpRequest.status === 200) {
        alert(httpRequest.responseText);
      } else {
        alert('There was a problem with the request.');
      }
    }
  }
})();
</script>

在这个例子中:

  • 用户在浏览器中单击链接“Make a request”;
  • 事件处理程序调用makeRequest()函数使用了参数 - 同一目录中的一个HTML文件的名称 test.html;
  • 请求被生成,然后  (onreadystatechange) 执行被传递到 alertContents();
  • alertContents() 检查是否收到响应,当它是一个 OK 时接着 alert()s  test.html 文件的内容.

注意:如果您向一个将返回XML而不是静态XMl文件的代码块发送请求,如若您的页面在IE浏览器甚至是Mozilla上展现并且使用,您最好设置一些响应标头信息。如若您并未设置header Content-Type:application/xml,IE会在您尝试访问的XML元素后面抛出一个JavaScript错误,“Object Expected”。

注意 2: 如果你不设置头Cache-Control:no-cache,浏览器将缓存响应,不再重新提交请求,使调试“具有挑战性”。您还可以附加一个始终不同的其他GET参数,如时间戳或随机数(请参阅绕过缓存)

注意 3:如果全局使用httpRequest变量,调用makeRequest()的竞争函数可能会相互覆盖,导致竞争条件。将包含AJAX函数的闭包声明为httpRequest变量可以防止竞争条件

如果发生通信错误(例如网络服务器关闭),尝试访问状态字段时,将在onreadystatechange方法中抛出异常。为了减轻这个问题,你可以包装你的if ... then语句在try ... catch:

function alertContents() {
  try {
    if (httpRequest.readyState === XMLHttpRequest.DONE) {
      if (httpRequest.status === 200) {
        alert(httpRequest.responseText);
      } else {
        alert('There was a problem with the request.');
      }
    }
  }
  catch( e ) {
    alert('Caught Exception: ' + e.description);
  }
}

步骤 4 – 使用XML响应

在前面的例子中,在接收到对HTTP请求的响应之后,我们使用了request对象的responseText属性,其中包含test.html文件的内容。现在让我们尝试使用responseXML属性。

首先,我们将在创建一个有效的XML文档之后发生请求。这个文档(test.xml)包含以下内容:

<?xml version="1.0" ?>
<root>
    I'm a test.
</root>

在脚本中,我们仅需要改变这条请求行:

...
onclick="makeRequest('test.xml')">
...

然后在alertContents()中,我们需要替换掉这一行输出(httpRequest.responseText);并且具备:

var xmldoc = httpRequest.responseXML;
var root_node = xmldoc.getElementsByTagName('root').item(0);
alert(root_node.firstChild.data);

This code takes the XMLDocument object given by responseXML and uses DOM methods to access some of the data contained in the XML document. You can see the test.xml here and the updated test script here.

步骤 5 – 使用数据

最后,让我们向服务器发送一些数据来收到回应。这次,我们的JavaScript代码会请求一个动态页面,test.php,这个页面会将接受我们发出的数据并且返回一个“被处理的”字符串 - “Hello,[user data]!” -这是我们将要输出的。

首先我们在HTML代码中添加一个文本框以便于用户键入他们的名字:

<label>Your name: 
  <input type="text" id="ajaxTextbox" />
</label>
<span id="ajaxButton" style="cursor: pointer; text-decoration: underline">
  Make a request
</span>

我们还需要在事件句柄处添加代码使得从文本框中得到用户的数据,再将数据通过URL发送到服务器端的脚本中的 makeRequest( ) 方法中:

  document.getElementById("ajaxButton").onclick = function() { 
      var userName = document.getElementById("ajaxTextbox").value;
      makeRequest('test.php',userName); 
  };

我们需要修改 makeRequest( ) 来接受用户数据并将其传给服务器。我们将请求方式从 GET 更改至 POST,并将我们的数据当作变量在 httpRequest.send( )中调用:

  function makeRequest(url, userName) {

    ...

    httpRequest.onreadystatechange = alertContents;
    httpRequest.open('POST', url);
    httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    httpRequest.send('userName=' + encodeURIComponent(userName));
  }

如果这就是服务器返回的所有内容,那么 alertContents( ) 这个方法在 第三步 中能以相同的方式输出我们被处理后的字符串。但是,假设服务器将同时返回被处理后的字符串和原始用户数据。如果我们的用户在文本框中键入“Jane”,那么服务器给出的响应应该是这样的:

{"userData":"Jane","computedString":"Hi, Jane!"}

为了配合 alertContents( ) 使用这条数据,我们不能仅仅输出 responseText,我们必须处理它并且输出我们想要的属性, computedString :

function alertContents() {
  if (httpRequest.readyState === XMLHttpRequest.DONE) {
    if (httpRequest.status === 200) {
      var response = JSON.parse(httpRequest.responseText);
      alert(response.computedString);
    } else {
      alert('There was a problem with the request.');
    }
  }
}

在 test.php 文件中应该包含一下代码:

$name = (isset($_POST['userName'])) ? $_POST['userName'] : 'no name';
$computedString = "Hi, " . $name;
$array = ['userName' => $name, 'computedString' => $computedString];
echo json_encode($array);

更多的DOM方法,请参见文档 Mozilla's DOM implementation 。

文档标签和贡献者

标签: 
 最后编辑者: soonj,