前段時間研究使用ionic構(gòu)建iOS-APP,結(jié)果在基本的網(wǎng)絡(luò)請求上都是各種磕磕碰碰,網(wǎng)上有效的資料也是相當少,現(xiàn)記錄如下以供后人參考。
ps:本人使用mac本,所述方法只在mac上使用過。
首先是在瀏覽器上對ionic構(gòu)建的網(wǎng)絡(luò)請求做調(diào)試,代碼如下:
http.service.ts里面
private getHeaders() {
const headers = {'Content-Type': 'application/json','Access-Control-Allow-Origin': '*','Access-Control-Allow-Methods': 'GET,POST,OPTIONS,DELETE,PUT'};
return new HttpHeaders(headers);
}
public post(url: string, params: any = null, successCallback, errorCallback): any {
return this.http.post(url, null, {
params: params,
headers: this.getHeaders(), // 添加token信息
}).subscribe((res: any) => {
this.responseSuccess(res, function (msg) {
if (successCallback) {
successCallback(res, msg);
}
});
}, err => {
if (errorCallback) {
errorCallback(err);
}
});
}
調(diào)用代碼:
const params = {
'username' : this.access,
'password' : this.password
};
console.log(params);
this.http.post('你自己的URL地址', params, (res, msg)=>{
console.log(res);
}, (err)=>{
console.log(err);
});
放心大膽的按著文檔敲完,然后調(diào)用過去,然后傻眼,報錯如下:
Access to XMLHttpRequest at '' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
啰哩吧嗦一大堆,簡單來說就是請求跨域了,而現(xiàn)在絕大部分瀏覽器為了安全,都是禁止跨域請求的,但是照著文檔敲代碼都能遇到這么大的坑,這個框架真是... ...無力吐槽,想知道跨域原理的自行百度,這里貼出本人的解決辦法。
打開終端,輸入如下命令:
open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-d
這里本人使用的是谷歌瀏覽器,用上面的命令可以打開一個暫時關(guān)閉跨域的谷歌瀏覽器窗口,在本窗口內(nèi)測試,可以繞過跨域問題。這樣就可以正常的在瀏覽器調(diào)試和開發(fā)了。
注意:只有新開的這一個窗口是關(guān)閉跨域的,別的窗口并不受影響,這個窗口關(guān)閉以后需要再次使用命令行打開。也許谷歌會提示你這樣不安全,關(guān)閉提示就行了。
在瀏覽器上調(diào)試完畢之后就可以上真機了,按官方文檔可以打包成Android和iOS各自的版本。Android本人沒嘗試過,在iOS真機測試的時候發(fā)現(xiàn)在瀏覽器上好不容易弄好的網(wǎng)絡(luò)請求又炸了,報錯如下:
{"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status":0,"statusText":"Unknown Error","url":"你的請求URL","ok":false,"name":"HttpErrorResponse","message":"Http failure response for 你的請求URL: 0 Unknown Error","error":{"isTrusted":true}}
這他媽的什么鬼!我完全對著官!方!文!檔!打包的好不好!??!
由于在真機上調(diào)試的時候代碼被編譯過了,暫未深入查驗原因。根據(jù)大佬的解釋,這是由于iOS的WebView機制造成的。
大家都知道,ionic用的是web的技術(shù),用ionic來搞APP,實際上就是個跑在手機web控件上的H5。而iOS的web控件經(jīng)歷了兩個時代,首先是UIWebView,后來因為這玩意的各種bug和緩存問題,蘋果又開發(fā)了WKWebView來替代前者,現(xiàn)在已經(jīng)要求強制使用WKWebView了。ionic在和UIWebView一起玩的時候,因為UIWebView不禁止跨域,所以一直順風順水,現(xiàn)在換上了WKWebView,正巧這又是一個禁止跨域請求的主,結(jié)果傻眼了。(我就知道混合不靠譜,就算沒這么巧合的事情,原生遲早也要找混合APP的茬,不給投入又想白用別人的生態(tài),哪有這么便宜的事情)
So:如果按官方的解釋這還是跨域問題,那么瀏覽器的跨域用命令行解決,真機咋辦呢?
官方給出的解決方案是使用ionic原生的請求插件,詳見官方文檔:https://ionicframework.com/docs/native/http/
代碼如下:
const params = {
'username' : this.access,
'password' : this.password
};
console.log(params);
this.httpY.setDataSerializer('urlencoded');
this.httpY.post('你自己的URL地址', params, {
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,POST,OPTIONS,DELETE,PUT'})
.then(data => {
console.log("backObj " + data.data);
let backObj = JSON.parse(data.data);
})
.catch(error => {
alert(error.error);
console.log("err " + error.status);
console.log("err " + error.error); // error message as string
console.log("err " + error.headers);
});
網(wǎng)上有人說ionic原生的請求插件很坑,就算對著文檔也難請求成功(因為官方文檔太潦草了),這里稍微記錄下本人使用中發(fā)現(xiàn)的需要注意的點:
1.注意setDataSerializer這個方法,請求body的數(shù)據(jù)類型實際上是這玩意控制的,正常應(yīng)該是請求頭里面設(shè)置'Content-Type'來控制body數(shù)據(jù)是text,或者是json什么的,但是ionic原生插件里面是用這個方法設(shè)置的,而且是全局的,一個地方設(shè)置,所有請求數(shù)據(jù)的類型全變,如果你的各個接口數(shù)據(jù)類型不一樣,那么需要在請求之前,分別設(shè)置!
2.返回數(shù)據(jù)data.data,這個是官方文檔給出的返回值獲取方式,但是這里的后一個data是string型,不是對象,在解析數(shù)據(jù)之前,需要先使用JSON.parse轉(zhuǎn)義一次,這個倒不是很坑,只是與我的使用習(xí)慣相悖。
最后記錄下本次問題解決過程中對我?guī)椭畲蟮囊黄恼?,表示感謝:
https://blog.csdn.net/u012365780/article/details/80449682