接受Ajax的命令

您是否要构建更动态,响应更快,类似于桌面的Web应用程序,例如Gmail和Google Maps? 那么本文适合您! 它会指导您完成Ajax基础知识以及构建简单的Ajax应用程序的过程。

该应用程序名为WebConsole,这是一个浏览器界面,用于执行您通常需要外壳程序访问的系统命令。 还有使用两个流行的JavaScript库jQuery和YUI的Ajax功能的简短示例。

在2005年首次发布并于最近更新的本文中,我将解释如何创建一个简单的,可重复使用的JavaScript函数来进行HTTP请求。 然后,我将在创建一个简单的应用程序中应用该功能。

尽管有一些YUI和jQuery示例,但本文不是有关特定Ajax库的教程。 相反,它旨在为您提供有关发出HTTP请求的更多动手信息,以便在评估此类库或决定自行运行时处于更好的位置。

一个简单的HTTP请求示例

首先,让我们修改在JavaScript中发出HTTP请求并处理响应的流程。 这只是刷新内存的简单示例。 有关所有令人毛骨悚然的细节,请参见SitePoint的介绍性文章“ Ajax:与远程脚本的可用交互性 ”。

有三个基本步骤:

  1. 创建一个XMLHttpRequest对象。
  2. 分配一个回调函数来处理HTTP响应。
  3. 提出(发送)请求。

让我们看一个示例,在该示例中,我们将请求一个简单的HTML文档test.html ,其中仅包含文本“我是测试”。 然后,我们将对test.html文件的内容进行alert()

<button id="mybutton">Make a request</button> 

<script type="text/javascript">

var http_request = false;

function makeRequest(url) {

  if (window.XMLHttpRequest) { // Mozilla, Safari, IE7...
      http_request = new XMLHttpRequest();
  } else if (window.ActiveXObject) { // IE6 and older
      http_request = new ActiveXObject("Microsoft.XMLHTTP");
  }
  http_request.onreadystatechange = alertContents;
  http_request.open('GET', url, true);
  http_request.send(null);

}

function alertContents() {
  if (http_request.readyState == 4) {
      if (http_request.status == 200) {
          alert(http_request.responseText);
      } else {
          alert('There was a problem with the request.');
      }
  }
}

document.getElementById('mybutton').onclick = function() {
  makeRequest('test.html');
}

</script>

此示例的工作方式如下:

  1. 用户单击“发出请求”按钮。
  2. 这将使用以下参数调用makeRequest()函数:同一目录中的HTML文件的名称。 在这种情况下,它是test.html
  3. 请求已发送。
  4. 触发onreadystatechange事件,并将执行传递给alertContents()
  5. alertContents()检查是否收到响应,如果还可以,则alert()包含test.html文件的内容。

自己测试示例 ,然后查看测试文件

问题

上面的例子很好用,但是在准备黄金时间之前,我们需要改进一件事。 改进之处在于编写了一个可重用的请求函数,该函数处理所有无聊且重复的对象创建和请求/响应内容,同时将表示部分留给其他函数,这些函数与请求无关,并且仅处理结果,无论其来源如何。

在上面的例子中,我们需要一个全局变量, http_request ,这是由两个访问makeRequest()alertContents()函数,这是不是在可重用性方面的良好和风险也命名冲突。 理想情况下, makeRequest()应该执行请求, alertContents()应该只显示结果; 这两个功能都不需要知道或不需要另一个。

这是我们可重用请求函数的代码:

function makeHttpRequest(url, callback_function, return_xml) 
{
 var http_request, response, i;

 var activex_ids = [
   'MSXML2.XMLHTTP.3.0',
   'MSXML2.XMLHTTP',
   'Microsoft.XMLHTTP'
 ];

 if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+...
   http_request = new XMLHttpRequest();
   if (http_request.overrideMimeType) {
     http_request.overrideMimeType('text/xml');
   }
 } else if (window.ActiveXObject) { // IE6 and older
   for (i = 0; i < activex_ids.length; i++) {
     try {
       http_request = new ActiveXObject(activex_ids[i]);
     } catch (e) {}
   }
 }

 if (!http_request) {
   alert('Unfortunately your browser doesn't support this feature.');
   return false;
 }

 http_request.onreadystatechange = function() {
   if (http_request.readyState !== 4) {
       // not ready yet
       return;
   }
   if (http_request.status !== 200) {
     // ready, but not OK
     alert('There was a problem with the request.(Code: ' + http_request.status + ')');
     return;
   }
   if (return_xml) {
     response = http_request.responseXML;
   } else {
     response = http_request.responseText;
   }
   // invoke the callback
   callback_function(response);
 };

 http_request.open('GET', url, true);
 http_request.send(null);
}

该函数接收三个参数:

  • 获取的URL
  • 收到响应时调用的函数
  • 如果回调函数需要XML文档( true )或纯文本( false ,默认值),则为一个标志

此函数依赖于两种JavaScript功能,以便很好地包装和隔离请求对象。 首先是能够即时定义新函数(称为匿名函数 )的能力,如下所示:

http_request.onreadystatechange = function() {...}

另一个技巧是能够在不事先知道回调函数名称的情况下调用回调函数。 例如:

var callmeback = alert;
callmeback('test'); // alerts 'test'

请注意如何传递不带引号的回调函数的名称。

您可以通过允许HTTP请求方法以及任何查询字符串作为参数传递给函数,然后在对open()send()方法的调用中使用,轻松地使该函数更加可重用。 除了最初打算执行的GET之外,这还允许您发出POST请求。

该功能的另一个功能是处理200以外的响应代码,如果您想更具体一些,并根据返回的成功/错误代码的类型采取适当的措施,这可能很方便。

重温简单的例子

现在,让我们重做前面的示例,其中对test.html文件的内容进行了alert()编辑。 这次,通过使用我们崭新的可重用请求函数,使用的两个函数的修订版将更加简单:

function alertContents(text) {  
  alert(text);  
}  

function makeRequest(url) {  
  makeHttpRequest(url, alertContents);  
}

如您所见,alertContents()只是表示性的:没有任何状态,readyStates或HTTP请求飞来飞去。

由于这些函数现在只是一线,实际上我们可以完全摆脱它们,而改为更改函数调用。 因此,整个示例将变为:

<button id="mybutton">Make a request</button> 
<script type="text/javascript">
 document.getElementById('mybutton').onclick = function() {
   makeHttpRequest('test.html', alert);
 }
</script>

是的,就是这么简单! 查看示例和完整的源代码 (可通过我们的老朋友查看源代码获得)。

我们的项目:WebConsole应用程序

了解Ajax的基础知识,并以一种可重用的方式提出请求,让我们更深入地创建一些可以在现实生活中实际使用的东西。

我们将创建的应用程序将允许您在Web服务器上执行任何Shell命令,无论它是基于Windows还是基于Linux。 我们甚至会花点CSS来尝试使该应用程序看起来更像一个控制台窗口。

在接口方面,我们有一个可滚动的<div> ,它包含了到目前为止执行的命令的结果,还有一个<input> ,在其中键入了要执行的命令。 它们都具有黑色背景和灰色信使字体。 这是屏幕截图。

WebConsole界面截图

HTML

这是应用程序的HTML部分:

<form action="exec.php" method="get" id="console-form">  
 <div  
   class="console"  
   id="result">  
   Welcome to the WebConsole!  
   <br />  
   :-&gt;  
 </div>  
 <input  
   class="console"  
   name="command"  
   id="command"  
   type="text" />  
</form>

就是这样:一个<div>随执行命令的结果更新,另一个<input>我们可以在其中键入命令。 这是一个非常干净的界面,没有<iframe>摔角,也没有页面重新加载-没什么!

CSS

样式表webconsole.css定义结果<div>和命令<input>的样式:

.console {  
   margin: 0px;  
   font-family: courier;  
   color: gray;  
   background-color: black;  
}  
#result {  
   overflow: auto;  
   padding: 5px;  
   height: 400px;  
}  
#result pre {  
   display: inline;  
}  
#command {  
   width: 100%;  
   border: 1px solid white;  
}

通过将其overflow属性设置为auto ,可以使显示命令执行结果的<div>可滚动。 我们还将<pre>标签的显示属性更改为inline (默认为block )。 还有一个可重用的.console类,使所有内容看起来都像“ consoley”:黑色背景上的灰色等宽字体。

服务器端代码

我们的应用程序将向服务器端脚本( exec.php )发出请求,该脚本通过GET参数'command'接收'command' 。 该脚本仅检查命令是否显示在允许列表中(您可以编辑此列表以允许更多命令),执行命令并打印结果。 该命令在本地PHP函数shell_exec()的帮助下执行。 这里使用PHP,但是使用您首选的服务器端语言来实现此功能应该相对容易。

<?php   
if(strcmp(strtoupper(substr(PHP_OS, 0, 3)), "WIN") == 0) {  
  // Windows commands  
  $allowed_commands = array ('cd', 'dir', 'more webconsole.css', 'more test.html', 'copy test.html test.txt', 'more test.txt', 'del test.txt');  
} else {  
  // Linux, Mac OS X, etc. commands  
  $allowed_commands = array ('ls -la', 'ls', 'ls -l', 'less webconsole.css', 'less test.html', 'touch test.txt', 'cp test.html test.txt', 'less test.txt', 'rm test.txt');  
}  
 
if (!empty($_GET['command']) && in_array($_GET['command'], $allowed_commands)) {  
  echo shell_exec($_GET['command']);  
} else {  
  echo "This demo version lets you execute shell commands only from a predefined list:n";  
  echo implode("n", $allowed_commands);  
}  
?>

警告!
$allowed_commands array限制用户可以通过控制台执行的命令。 您可以在阵列中添加任意数量的命令,但是请注意,任何其他命令都将在Web服务器上真正执行:例如,不建议添加format c:: apachectl stoprm –rf

JavaScript

JavaScript代码的第一步是定义一个名称空间 :一个美化的标签,本质上只不过是一个空对象:

var WebConsole = {};

我们需要的所有其他变量和函数将定义为该对象的属性。 这使我们可以保持全局名称空间的整洁和代码的独立。

应用程序中JavaScript代码的流程如下:

  1. WebConsole.keyEvent()函数附加到输入字段的onkeyup事件,并在每次按下和释放键时调用。
  2. WebConsole.keyEvent()检查是否按下了代码13的键(这是Enter / Return键)。
  3. 如果按下Enter键,则请求的URL的结构如下: exec.php?command=the-command-entered-by-the-user
  4. 该URL传递给我们可重用的makeHttpRequest()函数。 另外,回调函数的名称WebConsole.printResult作为makeHttpRequest()的参数提供。
  5. 成功的服务器响应后,将调用WebConsole.printResult()
  6. WebConsole.printResult()更新结果<div> ,向下滚动<div> ,并清除命令文本框,以便为下一个要键入的命令腾出空间。

这是keyEvent()函数的主体可能看起来像的样子:

WebConsole.keyEvent = function(event)   
{  
 switch(event.keyCode){  
   case 13:  
     var the_shell_command = document.getElementById('command').value;  
     if (the_shell_command) {  
       var the_url = 'exec.php?command=' + escape(the_shell_command);  
       makeHttpRequest(the_url, WebConsole.printResult);  
     }  
      break;  
    default:  
      break;  
  }  
}

因为我们没有将true作为第三个参数传递给makeHttpRequest() ,所以文本响应(非XML)将传递给printResult()

接下来,让我们看一下将更新结果<div>的函数。 有一种快速的方法来更新<div> ,即使用元素的innerHTML属性,如下所示:

document.getElementById('result').innerHTML += 'the-result-goes-here';

但是不建议使用innerHTML动态更新网页,因为它会将HTML代码视为字符串,而现代Web设计思想更倾向于将网页视为包含XML节点树的文档,可通过DOM方法和属性进行访问。 DOM是我们现在要采用的路径,以便更新我们的<div>

这是功能; 下面是有关其工作原理的一些说明:

WebConsole.printResult = function(result_string)  
{  
 var result_div = document.getElementById('result');  
 var result_array = result_string.split('n');  
 
 var new_command = document.getElementById('command').value;  
 result_div.appendChild(document.createTextNode(new_command));  
 result_div.appendChild(document.createElement('br'));  
 
 var result_wrap, line_index, line;  
 
 for (line_index in result_array) {  
   result_wrap = document.createElement('pre');  
   line = document.createTextNode(result_array[line_index]);  
   result_wrap.appendChild(line);  
   result_div.appendChild(result_wrap);  
   result_div.appendChild(document.createElement('br'));  
 }  
 result_div.appendChild(document.createTextNode(':-> '));  
 
 result_div.scrollTop = result_div.scrollHeight;  
 document.getElementById('command').value = '';  
};

该功能:

  • 通过创建新的文本节点并将其添加到文档树中,将在<input>输入的命令添加到结果<div>
  • 显示命令执行的结果。 通过将结果分成几行并将每行添加到文档树中,同时将每行包装在<pre>标记中以保留间距来完成。 我们需要分割结果,因为它可能包含多行(如果执行了'ls -la' (或Windows上的'dir' ),可以想象结果)
  • 添加一个新的类似光标的文本节点( :->
  • 使用scrollTopscrollHeight属性(非W3C标准,但受现代浏览器支持)向下滚动<div>
  • 清除命令<input>以便可以输入下一个命令

JavaScript中的最后一项任务是处理事件:

  • 表单提交只是“静音”,因此没有页面刷新
  • WebConsole.keyEvent()方法附加到输入命令的输入的keyup事件中。
document.getElementById('console-form').onsubmit = function(){  
   return false;  
};  
document.getElementById('command').onkeyup = function(e){  
   if (!e && window.event) {  
       e = window.event;  
   }  
   WebConsole.keyEvent(e);  
};

然后你去了! 这是难题的最后一部分。 现在,我们有了一个工作正常的Ajax应用程序 ,它是从头开始构建的。

一点额外

如果您对前面示例的源代码感到好奇,您可能已经注意到,此应用程序比到目前为止讨论的内容更多。 一点点与Ajax无关,但是它使应用程序更像是命令提示符。 所讨论的功能涉及使用向上和向下箭头键来访问会话中使用的命令的历史记录。

假设您先执行'ls -la' ,然后执行'ls' 。 如果您按下向上箭头键,则将在命令<input>中预填上次使用的命令; 即'ls' 。 再按一次向上箭头键,命令输入将显示'ls -la' 。 按下向下箭头键。 在命令的历史记录中再次到达'ls'自己尝试一下

实现此功能并不困难。 我们只需要一个数组来存储到目前为止执行的所有命令:

WebConsole.commands_history = [];

…和一个数组指针(一个整数),该指针可以记住我们在哪里:

WebConsole.history_pointer = 0;

这是WebConsole.keyEvent()函数的清单。 处理历史记录功能的行以粗体显示。

WebConsole.keyEvent = function(event)  
{  
 var the_url, the_shell_command;  
 switch(event.keyCode){  
   case 13:  
     the_shell_command = document.getElementById('command').value;  
     if (the_shell_command) {  
       this.commands_history[this.commands_history.length] = the_shell_command;  
       this.history_pointer = this.commands_history.length;
 
       the_url = 'exec.php?command=' + escape(the_shell_command);  
       makeHttpRequest(the_url, WebConsole.printResult);  
     }  
     break;  
 
   case 38: // this is the arrow up  
     if (this.history_pointer > 0) {  
       this.history_pointer--;  
       document.getElementById('command').value = this.commands_history[this.history_pointer];  
     }  
     break;  
   case 40: // this is the arrow down  
     if (this.history_pointer < this.commands_history.length - 1 ) {  
       this.history_pointer++;  
       document.getElementById('command').value = this.commands_history[this.history_pointer];  
     }  
     break;
 
   default:  
     break;  
 }  
};

以下是有关函数如何提供命令历史记录的一些说明:

  • 当我们按下Enter键(键代码13)并发出请求时,已执行的命令将添加到commands_history数组,并且数组指针将重置为该数组的新长度。
  • 当按下向上箭头(键代码38),表示“返回”时,我们递减history_pointer,并在历史记录列表中使用上一个命令预填充命令<input>
  • 按下向下箭头会使指针增加一个,然后我们看到下一个命令。

使用XML

到目前为止,我们还没有讨论如何请求和使用XML文档-Ajax中的X! 我们正在使用XMLHTTP对象的responseText属性。 请求文档与我们已经看到的没有什么不同:我们只需要指示我们的可重用请求函数返回responseXML ,而不是responseText 。 我们通过将第三个参数设置为truetrue

makeHttpRequest(the_url, 'printResult', true);

然后,我们需要更改exec.php脚本以返回有效的XML,而不是纯文本。 这是新脚本的源代码( exec_xml.php ):

<?php   
 
// $allowed_commands same as previous example  
 
header('Content-Type: text/xml');  
echo '<?xml version="1.0" ?>' . "n";  
echo '<exec>' . "n";  
echo '<command>' . htmlentities($_GET['command']) . '</command>' . "n";  
echo '<result>';  
if (!empty($_GET['command']) && in_array($_GET['command'], $allowed_commands)) {  
   $result = array();  
   exec($_GET['command'], $result);  
   if (!empty($result)) {  
       $result = array_map('htmlentities', $result);  
       echo '<line>';  
       echo implode("</line>n<line>", $result);  
       echo '</line>';  
   } else {  
       echo '<line>No output from this command. A syntax error?</line>';  
   }  
} else {  
   echo "<line>This demo version lets you execute shell commands only from a predefined list:</line>n";  
   echo '<line>';  
   echo implode("</line>n<line>", $allowed_commands);  
   echo '</line>';  
}  
echo '</result>' . "n";  
echo '</exec>';  
?>

这样,如果我们执行命令'ls test.html' ,新的服务器端脚本将返回以下内容:

<?xml version="1.0" ?>    
  <exec>    
      <command>ls test.html</command>    
      <result>    
          <line>test.html</line>    
      </result>    
  </exec>

如果执行返回更多行的命令(例如'ls -la' ),则响应中的每一行都将被包装在<line>标记中。

我们将使用JavaScript DOM函数浏览上述XML文档,以便处理<result>并将其显示在结果<div>

这是新的WebConsole.printResult()方法的主体:

WebConsole.printResult = function(xmldoc)   
{  
 var result_div = document.getElementById('result');  
 var result_collection = xmldoc.getElementsByTagName('line');  
 
 var new_command = xmldoc.getElementsByTagName('command')[0].firstChild.nodeValue;  
 result_div.appendChild(document.createTextNode(new_command));  
 result_div.appendChild(document.createElement('br'));  
 
 var number_of_items = result_collection.length;  
 var result_wrap, line;  
 for (var i = 0; i < number_of_items; i++) {  
   if (result_collection[i].hasChildNodes()) {  
     result_wrap = document.createElement('pre');  
     line = document.createTextNode(result_collection[i].firstChild.nodeValue);  
     result_wrap.appendChild(line);  
     result_div.appendChild(result_wrap);  
   }  
   result_div.appendChild(document.createElement('br'));  
 }  
 
 result_div.appendChild(document.createTextNode(':-> '));  
 
 result_div.scrollTop = result_div.scrollHeight;  
 document.getElementById('command').value = '';  
};

为了用XML文档中的数据更新结果<div> ,我们遵循以下过程:

  1. 从源XML访问节点。
  2. 获得其价值。
  3. 创建一个新节点。
  4. 将其附加到<div>目标树。

如您在代码中所见,使用了xmldoc.getElementsByTagName'command' ),它返回所有<command>节点的集合(类似于数组的列表对象)。 在我们的例子中,只有一个这样的节点。 我们通过以下方式获取其价值:

xmldoc.getElementsByTagName('command')[0].firstChild.nodeValue;

我们获取节点值,并创建一个新的文本节点以附加到<div> ,如下所示:

var new_command = xmldoc.getElementsByTagName('command')[0].firstChild.nodeValue; 
result_div.appendChild(document.createTextNode(new_command));

我们对XML文档的<result>标签执行相同的操作。 首先,我们得到所有<line>

var result_collection = xmldoc.getElementsByTagName('line');

然后,我们遍历result_collection每个元素。 同样,我们将结果的每一行都包装在<pre>标记中。

如您所见,使用XMLDocument并不比使用纯文本响应困难得多。 您可以自己测试WebConsoleXML版本

使用jQuery

jQuery是一个流行的JavaScript库。 让我们尝试将其用于我们的Ajax功能,而不是可重用的makeHttpRequest()函数。

首先,您需要从此处下载该库的最新版本(我建议使用缩小版)并将其包含在页面中:

<script type="text/javascript" src="jquery-1.2.3.min.js"></script>

在过去,我们曾经这样称呼makeHttpRequest()

the_url = 'exec.php?command=' + escape(the_shell_command);
makeHttpRequest(the_url, WebConsole.printResult);

现在,使用jQuery的Ajax()方法可以执行以下操作:

var xhr = $.Ajax({
url: 'exec.php',
data: {'command': the_shell_command},
success: WebConsole.printResult
});

让我们看看这里有什么:

  • $是jQuery的快速名称; 您也可以改为执行以下操作: jQuery.Ajax
  • 我们调用Ajax()方法,并传递一个包含URL的对象,一个数据对象(将通过jQuery进行转义并将其转换为查询字符串)和一个回调函数,以在响应到达时进行调用。

这里是使用jQuery的Web控制台的工作示例。

有更多使用jQuery的Ajax的方法,有关文档的确认。 例如,使用文件( test.html )的内容更新<div> (ID为mydiv )的一项经常重复的任务可能很简单:

$("#mydiv").load("test.html");

在这里查看示例。

使用YUI

另一个流行的JavaScript库是YUI (Yahoo接口库)。 让我们看看如何使我们的Web控制台与YUI的Ajax功能一起使用。

我们不需要下载YUI文件,因为Yahoo已经免费托管了它们并且可以从其当前位置使用它们。 连接管理器实用程序提供了Ajax功能,您可以将其包括在页面中,如下所示:

<script type="text/javascript" src="http://yui.yahooapis.com/2.5.1/build/yahoo/yahoo-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.5.1/build/event/event-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.5.1/build/connection/connection-min.js"></script>

现在,为了利用YUI,我们makeHttpRequest()的调用替换为:

// YUI's Ajax
YAHOO.util.Connect.asyncRequest(
'GET',
'exec.php?command=' + escape(the_shell_command),
{
success: function(xhr){
WebConsole.printResult(xhr.responseText)
}
}
);

您可以看到asyncRequest()方法采用:

  • 请求方法(GET,POST,HEAD,DELETE等)
  • 网址
  • 包含用于处理成功和失败方案的函数的对象

YUI将XMLHttpRequest对象传递给处理程序函数,因此在这种情况下,我们只获取responseText的内容并将其转发给printResult()

您可以查看如何通过串联和转义字符串来创建URL。 在这种情况下,我们只想通过查询字符串传递一个值。 但是,如果还有更多,它将变得非常不便。 YUI通过提供setForm()方法来帮助您轻松处理此类情况。 设置表单后,YUI将从表单中获取值,并进行转义和缝合查询字符串的操作:

YAHOO.util.Connect.setForm(document.forms[0]);
YAHOO.util.Connect.asyncRequest(
'GET',
'exec.php',
{
success: function(xhr){
WebConsole.printResult(xhr.responseText)
}
}
);

这是使用YUI的Web控制台的工作示例

使用JSON

JSON(JavaScript对象表示法)是一种流行的数据交换格式。 在将数据从服务器传递到浏览器时,它为纯文本或XML提供了另一种选择。 JSON非常简单; 本质上,它只是JavaScript。

在JavaScript中,您可以定义一个数组和一个对象,如下所示:

var a = new Array(1,2,3);
var o = new Object();
o.property = 'value';
o.property2 = 2;

您可以执行相同操作,但使用数组和对象文字,如下所示:

var a = [1,2,3];
var o = {'property': 'value', 'property2': 2};

此文字表示法是JSON用于传递数据的方式。 大多数时候,JavaScript适当的属性周围的引号不是必需的,但按照惯例,JSON中是必需的。

让我们更改控制台,使其使用JSON格式传输数据。 流程为:

  1. 服务器端的PHP使用结果创建一个关联数组,然后使用仅PHP5的内置函数json_encode()将其转换为JSON,但是即使手动编码响应也很简单。 返回JSON字符串。
  2. 浏览器中的JavaScript接收JSON字符串,并将其转换为本地JavaScript对象。 一种不安全的方法是使用eval()函数。 更好的方法是使用免费的JSON库

例如,如果我们执行的命令是ls ,则来自服务器的JSON响应将类似于以下内容(为便于阅读,对其进行了格式化和删节):

{   
   "command":"ls",  
   "result":[  
       "exec.php",  
       "exec_json.php",  
       "exec_xml.php",  
       "httprequest_example.html",  
       "httprequest_test.html"  
       // ... and so on  
   ]  
}

如您所见,JSON没有XML轻巧,因为没有结束标记,XML文档标记或根节点。

更改我们的服务器端脚本以返回JSON会导致如下所示:

exec_json.php:    
 
<?php  
 
// $allowed_commands same as before  
 
$return = array('command' => $_GET['command']);  
 
if (!empty($_GET['command']) && in_array($_GET['command'], $allowed_commands)) {  
   $result = array();  
   exec($_GET['command'], $result);  
   if (!empty($result)) {  
       $return['result'] = $result;  
   } else {  
       $return['result'] = array('No output from this command. A syntax error?');  
   }  
} else {  
 
   $return['result'] = $allowed_commands;  
   array_unshift(  
       $return['result'],  
       'This demo version lets you execute shell commands only from a predefined list:'  
   );  
}  
 
echo json_encode($return);  
?>

在JavaScript中, WebConsole.printResult接受数据的部分将变为:

WebConsole.printResult = function(json_string)   
{  
 var data = eval('('+ json_string +')');  
 var result_array = data.result;  
   
 // ... same as before  
}

您可以看到eval() ,数据如何成为普通的JavaScript对象,并且可以访问其属性,例如data.resultdata.command 。 如前所述, eval()是一种将JSON编码的字符串转换为对象的不安全方法。 更好的方法是使用JSON库 ,该可帮助我们用以下代码替换eval()调用:

var data = JSON.parse(json_string);

一个工作的JSON示例在这里

安全提醒
为了演示此应用程序 ,我只允许在Web服务器上执行一组预定义的无害命令。 如果您展开命令列表或允许任何命令,请不要忘记保护服务器上要安装应用程序的目录。 让陌生人可以访问该应用程序可能会造成灾难性的后果。 它非常强大:它将允许用户执行任何命令,包括但不限于删除Web服务器上的所有内容!

结论

我们到了示例Ajax应用程序的结尾。 您了解基本知识,看到了动作,并且已经掌握了足够的知识来开始尝试自己。 您可以通过修改和试用本文的代码进行预热(它们全部包含在可下载的代码档案中) ,然后移至您自己的项目。

这是一段激动人心的时刻:由于远程脚本编写,Web的面貌正在发生重大变化。 我们已经经历了早期采用者(Google,Amazon,Flickr,Yahoo)的阶段,现在在创建响应式和用户友好的网页时,使用Ajax进行远程脚本编写变得越来越普遍。 如今,使用GMail和Flickr已经破坏了访问者,您无法承受用静态Web 1.0样式的页面侮辱他们的风险!

From: https://www.sitepoint.com/take-command-ajax/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值