最近在项目中有这样一个需求:在前端页面的js文件中从后台获取一个URL,拿到URL后调用windows.open方法打开这个URL。URL由后端程序拼接而成,在开发过程中遇到了两个问题,前端js代码如下:
showWindow : function() {
Fw.Ajax.request({
url : '/ebank/callCenter.do',
params : {'COMPY_NAME':COMPY_NAME},
page : false,
success : function(data) {
callCenterUrl = data.call_center_url;
},
if(callCenterUrl != null) {
window.open(callCenterUrl,'_blank','width=850, height=600, resizable=yes, toolbar=no, menubar=no');
}else {
alert("客服系统繁忙,请稍后再试");
}
onFailure : function() {
},
});
},
1.可能出现先弹出窗口,后拿到URL的情况
- 上面代码经常出现打开空白页面的结果,分析原因是Ajax异步请求后端,还没拿到URL就执行了windows.open方法导致打开了空白页(URL初始值赋的“_blank”)
- 尝试解决了一下,将弹窗逻辑放在回调函数success中,确实可以保证先拿到URL后再执行windows.open方法,但是又引出了一个新的问题。
2.浏览器拦截弹窗问题
- 将弹窗逻辑放入Ajax的回调函数success中后,弹出窗口在IE浏览器遭到拦截:
其原因是浏览器出于安全策略阻挡了非用户点击弹出的窗口,所谓非用户点击就是弹出的窗口不是直接由用户点击事件触发的弹窗。在这段逻辑当中,弹窗事件由程序发起,所以会被浏览器拦截。然而对于用户来说这种体验肯定是不好的,你不能指望一个用户对浏览器以及程序了如指掌。于是通过搜索找到一种解决方法,更新后的代码如下:
showWindow : function() {
//先打开窗口,防止放进Ajax中被浏览器拦截
var adPopup = window.open(callCenterUrl,'_blank','width=850, height=600, resizable=yes, toolbar=no, menubar=no');
Fw.Ajax.request({
url : '/ebank/callCenter.do',
params : {'COMPY_NAME':COMPY_NAME},
page : false,
success : function(data) {
callCenterUrl = data.call_center_url;
if(callCenterUrl != null) {
//避免被浏览器拦截,重定向窗口
adPopup.location = callCenterUrl;
}else {
alert("客服系统繁忙,请稍后再试");
}
},
onFailure : function() {
},
});
},
- 上述JS代码将打开窗口动作放在了监听按钮点击事件下,在Ajax函数执行之前,我在项目本地加了一个loading动画的页面,在拿到真正后台传来的URL之前,弹出的窗口都会在这个Loading页面等待。一旦Ajax返回了真正的URL,再将窗口重定向到新的URL。经过这种设置,成功解决了弹窗被浏览器拦截的问题。
3.对Ajax的好奇与初步探索
- Ajax是什么
AJAX is not a programming language. It is just a technique for creating better and more interactive web applications.
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下刷新局部页面。 - Ajax怎么实现的
- 实际使用了几次Ajax与后台进行交互后,我不禁在想,这么好用的技术是怎么实现的?初步猜测是另起了一个线程,在子线程里进行操作,然后在子线程里对局部页面进行更新。
- 经过搜索,得知Ajax请求的核心是
XMLHttpRequest
,原来整个Ajax与后台交互与刷新局部页面的技术是这个对象。对于XMLHttpRequest的介绍有很多,这里仅贴Ajax实现封装以辅助自己记忆。代码来自 AJAX的实现原理以及封装
var $={
/*传递参数对象,返回拼接之后的字符串*/
/*{‘name’:’jack,’age’:20}=> name=jack&age=20&*/
getParmeter:function(data){
var result="";
for(var key in data){
result=result+key+"="+data[key]+"&";
}
/*将结果最后多余的&截取掉*/
return result.slice(0,-1);
},
/*实现ajax请求*/
ajax:function(obj){
/*1.判断有没有传递参数,同时参数是否是一个对象*/
if(obj==null || typeof obj!="object"){
return false;
}
/*2.获取请求类型,如果没有传递请求方式,那么默认为get*/
var type=obj.type || 'get';
/*3.获取请求的url location.pathname:就是指当前请求发起的路径*/
var url=obj.url || location.pathname;
/*4.获取请求传递的参数*/
var data=obj.data || {};
/*4.1获取拼接之后的参数*/
data=this.getParmeter(data);
/*5.获取请求传递的回调函数*/
var success=obj.success || function(){};
/*6:开始发起异步请求*/
/*6.1:创建异步对象*/
var xhr=new XMLHttpRequest();
/*6.2:设置请求行,判断请求类型,以此决定是否需要拼接参数到url*/
if(type=='get'){
url=url+"?"+data;
/*重置参数,为post请求简化处理*/
data=null;
}
xhr.open(type,url);
/*6.2:设置请求头:判断请求方式,如果是post则进行设置*/
if(type=="post"){
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
}
/*6.3:设置请求体,post请求则需要传递参数*/
xhr.send(data);
/*7.处理响应*/
xhr.onreadystatechange=function(){
/*8.判断响应是否成功*/
if(xhr.status==200 && xhr.readyState==4){
/*客户端可用的响应结果*/
var result=null;
/*9.获取响应头Content-Type ---类型是字符串*/
var grc=xhr.getResponseHeader("Content-Type");
/*10.根据Content-Type类型来判断如何进行解析*/
if(grc.indexOf("json") != -1){
/*转换为js对象*/
result=JSON.parse(xhr.responseText);
}
else if(grc.indexOf("xml") != -1){
result=xhr.responseXML;
}
else{
result=xhr.responseText;
}
/*11.拿到数据,调用客户端传递过来的回调函数*/
success(result);
}
}
}
};
调用方式与jquery类似的:
$.ajax({
url:'',
type:'',
data: {},
success:function(result){
//code...
}
});
- Ajax出现已经有近20历史,是否有替代技术?
- 通过我的搜索,发现了一个传说中将会取代Ajax的技术,叫做Fetch,当然了,具体能不能取代Ajax可能还要继续观察,但是对于这技术了解一下总是好的。
- 引用W3C School的一段话:十多年来,XMLHttpRequest 对象一直被 AJAX 操作所接受,但是我们知道,XMLHttpRequest 对象的 API 设计并不是很好,输入、输出、状态都在同一个接口管理,容易写出非常混乱的代码。那么Fetch API就应势而生,提供了一种新规范,用来取代善不完美的 XMLHttpRequest 对象。
Fetch API 主要有两个特点:一是接口合理化,AJAX 是将所有不同性质的接口都放在 XHR 对象上,而Fetch是将它们分散在几个不同的对象上,设计更合理;二是Fetch操作返回 Promise 对象,避免了嵌套的回调函数。
接下来将花点时间学习一下Fetch,先附上Fetch API官方文档。
网友评论