我正试图使用这个AJAX请求来调用一个文件,其中一些PHP运行正常,而一些JavaScript运行不正常。有什么想法吗?
function showpart2(){
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","atuamae.org/parte2-encomendar.php",false);
xmlhttp.send(null);
}
document.getElementById('part2').innerHTML = xmlhttp.responseText;
eval(xmlhttp.responseText.getElementById('part2').innerHTML)
setTimeout('showpart2()',15000);
}
showpart2();
示例代码的一个大问题是,使XMLHttpRequest.send
同步意味着所有JS执行都必须暂停,同时等待接收到请求。没有理由不使用异步调用。
异步调用可以提高响应能力,但它们不能提供协调,这意味着在准备好所需的数据之前,任务不会运行。协调异步代码的标准方法是将一个函数传递给异步函数,该函数在执行时执行依赖于数据的其余计算。该功能的技术名称为";"延续";,它只是一个函数,表示从给定点向前的其余计算。也就是说,转向:
f1();
f2();
async();
f3();
f4();
进入:
f1();
f2();
async(function() {
f3();
f4();
});
因为你在传递一个延续,这被称为";延续传球风格";。XMLHttpRequest是一种特殊情况,因为您没有将函数传递给异步函数,而是将其设置为XHR对象上readystatechange
事件的侦听器。也就是说,您将延续指定给xmlhttp.onreadystatechange
。
还有一些改进需要改进。首先,添加错误检测。XHR实例的status
属性保存HTTP状态,您可以使用它来检查错误。
正如许多其他人所提到的,eval
可能会有问题,在有其他选择时应该避免。首先,您必须确保字符串来自可信来源。这里eval
的特殊问题是在与调用eval
相同的上下文中评估脚本。如果eval
发生在函数内部,则脚本定义的任何内容在函数外部都不可见。如果您的脚本不需要定义任何东西(也永远不需要定义什么;始终考虑代码的未来(,则可以使用eval
。否则,以脚本为内容动态创建一个脚本元素,并将其添加到文档中;您可以定义一个执行此操作的函数(请参阅下面示例中的globaleval
(。
xmlhttp
是一个全局变量,这是不好的。相反,将其声明为局部变量。
使用setInterval
,而不是用于一次性调用的setTimeout
,它周期性地调用传递的函数。请注意,setTimeout
和setInterval
可能需要比给定延迟更长的时间才能运行,尽管这在这里应该不是问题。
(function () {
// keep variable from polluting global namespace
var showpart2Interval = 0,
scriptElt = {parentNode: {removeChild: function() {}}};
function globaleval(script) {
scriptElt.parentNode.removeChild(scriptElt);
scriptElt = document.createElement('script');
scriptElt.type = 'text/javascript'
scriptElt.appendChild(document.createTextNode(script));
document.body.appendChild(scriptElt);
}
function showpart2(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","atuamae.org/parte2-encomendar.php",false);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (200 <= xmlhttp.status && xmlhttp.status < 300) {
globaleval(xmlhttp.responseText);
} else {
// HTTP error
...
}
}
}
xmlhttp.send(null);
}
function startShowpart2() {
if (window.XMLHttpRequest && !showpart2Interval) {
showpart2();
showpart2Interval = setInterval(showpart2, 15000);
}
}
function stopShowpart2() {
clearInterval(showpart2Interval);
showpart2Interval = 0;
}
window.startShowpart2 = startShowpart2;
window.stopShowpart2 = stopShowpart2;
})();
startShowpart2();
如果您不关心自己实现所有这些,请让jQuery来承担重任。知道如何自己动手是件好事,但(对于生产代码(使用具有标准接口的标准库可以在许多方面加快开发。
另请参阅
- Javascript:设置函数的顺序
您需要实际评估JS标记(手动,通过eval
或通过DOM插入(。像jQuery这样的库可以帮你做到这一点,但如果你需要使用自定义解决方案,你也需要添加它。
您编写:
xmlhttp.responseText.getElementById("第2部分"(
responseText是一个字符串,不会有任何getElementById方法。您可以使用xmlhttp.responseXML.getElementById("part2"(,也可以使用字符串方法提取第二部分。
像Adam Rackis一样,我建议你使用$.ajax。yyy很容易尝试……但如果它不是你的选择,这里有一个函数,用于进行ajax调用,并在IE和Firefox中工作,如果你不能使用Jquery,我建议Chrome。函数中的问题在IE中不起作用,因为它没有xmlhttprequest对象。希望这对你有帮助。
function newAjaxObject()
{
var oHttp=false;
var asParsers=[
"Msxml2.XMLHTTP.5.0",
"Msxml2.XMLHTTP.4.0",
"Msxml2.XMLHTTP.3.0",
"Msxml2.XMLHTTP",
"Microsoft.XMLHTTP"
];
if ( !oHttp && typeof XMLHttpRequest != 'undefined')
{
oHttp=new XMLHttpRequest();
}
if( !oHttp){
for (var iCont=0; !oHttp && iCont < asParsers.length; iCont++)
{
try
{
oHttp=new ActiveXObject(asParsers[iCont]);
}
catch(e)
{
oHttp=false;
}
}
}
return oHttp;
}