我刚刚开始使用Phonegap和一般的移动开发,并且我试图调用$.ajax(…)来做任何当从iOS模拟器或iOS设备运行时-但是我的小应用程序在从浏览器或Ripple模拟器(http://ripple.incubator.apache.org/)运行时都工作得很好。
此外,我已经熟悉了CORS,并且我的测试似乎表明,我的请求/响应标头已正确设置为跨域客户机-服务器通信。使用Safari WebInspector的JS调试器逐步执行(并监视服务器的Apache日志),我已经能够确定对xhr.send()的调用从未实际执行过。
一旦我意识到这一点,我就从公式中删除了jQuery,以防我不正确地设置$.ajax()请求,并且我使用下面的代码创建CORS请求(从这里获得:http://www.html5rocks.com/en/tutorials/cors/)
在这两种情况下(使用和不使用jQuery),我注意到在调试器中调用xhr.open(…)之后,xhr.open(…)的值。Status和xhr。statusText都设置为"[Exception: DOMException]",我假设这是阻止xhr.send()执行的原因。
另外,config.xml包含以下行:
<access origin="*" />
下面是创建和执行请求的代码:
// Create the XHR object.
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// XHR for Chrome/Firefox/Opera/Safari.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// XDomainRequest for IE.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// CORS not supported.
xhr = null;
}
return xhr;
}
// Helper method to parse the title tag from the response.
function getTitle(text) {
return text.match('<title>(.*)?</title>')[1];
}
// Make the actual CORS request.
function makeCorsRequest() {
// All HTML5 Rocks properties support CORS.
var url = 'http://server.mylocalhost/api/action?arg1=foo';
var xhr = createCORSRequest('GET', url);
if (!xhr) {
alert('CORS not supported');
return;
}
// Response handlers.
xhr.onload = function() {
var text = xhr.responseText;
var title = getTitle(text);
alert('Response from CORS request to ' + url + ': ' + title);
};
xhr.onerror = function() {
alert('Whoops, there was an error making the request.');
};
xhr.send();
}
注意:上面在makeCorsRequest()中指定的url反映了我在应用程序中所针对的url的实际结构。
我设置:- ajax请求两端的完全控制
- 本地开发,客户端和服务器使用独立的apache虚拟主机(例如http://server.mylocalhost和http://mobile.mylocalhost)
- 所有内容的最新版本(Phonegap/Cordova, Xcode, Ripple, Chrome, Safari, Jquery, OSX/Mavericks等)
另外,我不喜欢使用JSONP。
这原来是网络(DNS)层的问题。事实证明,Xcode iOS模拟器忽略了主机的/etc/hosts文件,并且似乎没有等效的方法来控制模拟器环境中的DNS。因此,据我所知,使用基于名称的虚拟主机在本地开发机器上进行开发是不可能的……这似乎是一个相当荒谬的限制。
由于iOS模拟器显然确实知道如何找到"localhost",我通过将以下行添加到虚拟主机的VirtualHost容器中来解决我的问题,虚拟主机是我的目标API端点(在适当的Apache配置文件中):
ServerAlias localhost
然后我将makeCorsRequest()中的url更改为以下形式:
var url = 'http://localhost/api/action?arg1=foo';
在基于jquery的版本中进行类似的更改也有效。
可能有其他更好的方法来解决这个令人难过的限制,但是现在这个修复已经允许我回到实际关注我的应用程序。