ajax请求里面调用window.open会被浏览器拦截

本文介绍了解决在业务系统中使用window.open()方法跳转到支付页面时遇到的自动拦截问题。通过调整代码逻辑,确保了弹窗能够正常显示,并提供了两种不同业务场景下的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景:
业务系统需要跳转到其他系统-支付平台去完成支付,使用的 window.open(url),跳转之前需要做一系列的ajax验证,
那么问题来了,window.open放在ajax校验完成并且成功后才会调用,这时浏览器会觉得这个弹窗不是用户操作想看到的,
所以自动进行了拦截!

上述问题在我解决问题时,也分为了两种场景:

一、ajax 返回成功后立即调用window.open()方法,代码如下:

//去支付
function gotoPay(param) {
	$.ajax({
		type: "post",
		url: "/xxxx/xxxx",
		data: {"param": param},
		error: function (data) {
			showError(data);
		},
		success: function (data) {
			if (data.errorFlag == 0) {
				window.open("www.baidu.com");
			} else {
				layer.alert(data.desc, {icon: 2, title: '提示信息'})
			}
		}
	});
}

对应的解决方案(在ajax执行前先打开窗口):

//去支付
function gotoPay(param) {
	// 新加
	var newTab=window.open('about:blank');
	$.ajax({
		type: "post",
		url: "/xxxx/xxxx",
		data: {"param": param},
		error: function (data) {
			showError(data);
		},
		success: function (data) {
			if (data.errorFlag == 0) {
				// 新加
				newTab.location.href = "www.baidu.com";
			} else {
				layer.alert(data.desc, {icon: 2, title: '提示信息'})
			}
		}
	});
}


二、 ajax执行后,还需要对ajax返回结果进行业务判断,根据不同的业务还需要弹出确认框进确认,然后根据相应的操作再决定是否跳转,

那么这里如果还是跟场景一一样的ajax调用执行前就打开窗口的话,很显然交互上面就不合适了,代码如下:

//去支付
function gotoPay(param) {
	$.ajax({
		type: "post",
		url: "/xxxx/xxxx",
		data: {"param": param},
		error: function (data) {
			showError(data);
		},
		success: function (data) {
			if (data.errorFlag == 0) {
				if (data.status == 1) {
				
					// 和场景一的区别就是这里需要根据业务状态弹框确认
					layer.open({
						//type: 1,
						icon: 3,
						area: ['500px', 'auto'],
						title: "支付",
						btn: ['确认支付', '取消'],
						content: "订单当前状态为xxxxxx,确认继续支付吗?",
						btn1: function (index) {
							layer.closeAll();
							window.open("www.baidu.com");
						},
						btn2: function (index) {
							layer.closeAll();
						}
					});
				} else {
					window.open("www.baidu.com");
				}
			} else {
				layer.alert(data.desc, {icon: 2, title: '提示信息'})
			}
		}
	});
}


对应的解决方案如下:

//去支付
function gotoPay(param) {
	$.ajax({
		type: "post",
		url: "/xxxx/xxxx",
		async: false,// 只加了个同步
		data: {"param": param},
		error: function (data) {
			showError(data);
		},
		success: function (data) {
			if (data.errorFlag == 0) {
				if (data.status == 1) {
				
					// 和场景一的区别就是这里需要根据业务状态弹框确认
					layer.open({
						//type: 1,
						icon: 3,
						area: ['500px', 'auto'],
						title: "支付",
						btn: ['确认支付', '取消'],
						content: "订单当前状态为xxxxxx,确认继续支付吗?",
						btn1: function (index) {
							layer.closeAll();
							window.open("www.baidu.com");
						},
						btn2: function (index) {
							layer.closeAll();
						}
					});
				} else {
					window.open("www.baidu.com");
				}
			} else {
				layer.alert(data.desc, {icon: 2, title: '提示信息'})
			}
		}
	});
}


综上,根据不同的业务需求,对应不同的解决方法,不过如果不是必须一定要用异步的话,场景二的解决办法改动最小,最实用!!!

上述两种方法测试通过 chrome   Firefox  ie 





<think>我们正在解决浏览器拦截`window.open`打开新窗口的问题。根据引用资料,主要原因是浏览器的安全机制会拦截非用户直接触发的`window.open`调用。以下是几种解决方案: 1. **将`window.open`直接绑定在用户操作事件上**:确保`window.open`是由用户点击按钮等事件直接触发,而不是在异步回调(如Ajax请求成功后的回调)中触发。如果是异步操作,可以先打开一个空白窗口,然后在异步操作完成后修改该窗口的URL。 2. **先打开空白窗口再设置URL**:在用户操作事件中,先打开一个空白窗口(`window.open('about:blank')`),然后在异步操作(如Ajax请求)完成后,将空白窗口的`location.href`设置为目标URL。 3. **使用表单提交**:创建一个表单,设置`action`为目标URL,然后在用户操作事件中提交表单。因为表单提交是被浏览器允许的,通常不会被拦截。 4. **延迟打开窗口**:在某些情况下,将`window.open`放在`setTimeout`中(延迟时间很短,如1毫秒)可能绕过拦截,但这种方法并不总是有效。 根据引用[2]和[4]的示例,我们可以采用以下方法: **方法1:先打开空白窗口再重定向(推荐)** ```javascript async function openWindow(url) { // 在用户点击事件中直接打开空白窗口 const newWindow = window.open('about:blank'); // 这里可以添加一些异步操作,比如等待数据 // await someAsyncFunction(); // 然后重定向 newWindow.location.href = url; } ``` **方法2:使用表单提交(推荐)** ```html <form id="hiddenForm" action="目标URL" method="get" target="_blank" style="display:none;"> </form> <script> function openWindow(url) { const form = document.getElementById('hiddenForm'); form.action = url; form.submit(); } </script> ``` 或者动态创建表单: ```javascript function openWindow(url) { const form = document.createElement('form'); form.action = url; form.method = 'get'; form.target = '_blank'; document.body.appendChild(form); form.submit(); document.body.removeChild(form); } ``` **注意**:方法1中,如果异步操作时间较长,用户可能会看到一个空白窗口,体验可能不好。因此,如果目标URL是已知的,且不需要等待异步操作,最好直接使用`window.open`(在用户事件中)。如果URL需要异步获取,则先打开空白窗口再重定向是可行的。 根据引用[5],使用表单提交也是一种有效且稳定的方法,因为表单提交是同步操作,不会被浏览器拦截。 因此,针对你的问题,建议: - 如果URL是已知的,在用户点击事件中直接使用`window.open(url)`。 - 如果URL需要异步获取,则先调用`window.open('about:blank')`打开空白窗口,然后在获取到URL后设置`newWindow.location.href = url`。 - 或者使用表单提交方式(同步或异步设置表单的action后提交)。 请根据你的具体情况选择合适的方法。 §§相关问题§§ 1. 如何判断浏览器是否拦截了`window.open`打开的窗口? 2. 除了`window.open`,还有哪些方法可以打开新窗口且不被拦截? 3. 在单页应用(SPA)中如何优雅地处理外部链接的打开?</think>### 解决浏览器拦截 window.open 的方法 当使用 `window.open()` 打开外部链接时被浏览器拦截,这是因为浏览器的安全机制会阻止 **非用户直接触发的弹窗**。以下是几种有效的解决方案: #### ✅ 方案1:先打开空白窗口再重定向(推荐) ```javascript function safeOpen(url) { // 用户操作中直接打开空白窗口 const newWindow = window.open('about:blank'); // 异步操作完成后重定向 setTimeout(() => { newWindow.location.href = url; // 关键步骤 }, 0); } // 调用示例(必须在用户点击事件内) button.addEventListener('click', () => { safeOpen('https://external.com'); }); ``` **原理**:浏览器允许用户操作中立即打开的窗口,后续通过修改 `location.href` 重定向不会被拦截[^2][^4]。 #### ✅ 方案2:使用表单提交跳转 ```html <form id="hiddenForm" action="https://external.com" method="get" target="_blank" style="display:none;"> </form> <script> function safeOpen(url) { const form = document.getElementById('hiddenForm'); form.action = url; form.submit(); // 表单提交不会被拦截 } </script> ``` **原理**:表单提交属于浏览器白名单操作,不受弹窗拦截限制[^5]。 #### ✅ 方案3:直接绑定到用户事件 ```javascript // 正确做法(直接在用户事件中调用) button.onclick = () => { window.open('https://external.com'); // 直接触发 }; // 错误做法(会被拦截) button.onclick = async () => { await fetchData(); // 异步操作 window.open('https://external.com'); // 非直接触发 }; ``` **原理**:浏览器只允许 **与用户操作同步执行** 的 `window.open`[^1][^3]。 --- ### 关键注意事项 1. **必须由用户操作触发** 所有解决方案都需直接绑定到 `click`、`submit` 等用户事件,不能通过 `setTimeout` 延迟执行或放在异步回调中。 2. **现代浏览器的处理差异** - Chrome/Firefox:会显示 "弹出式窗口已阻止" 提示栏 - Safari:完全静默阻止 - 移动端浏览器拦截策略更严格 3. **替代方案** 考虑使用 `<a target="_blank">` 标签替代 JS 跳转: ```html <a href="https://external.com" target="_blank">打开链接</a> ``` --- ### 相关问题 1. 如何检测 `window.open` 是否被浏览器拦截? 2. 在单页应用(SPA)中如何处理外部链接打开才不会被拦截? 3. 除了 `window.open`,还有哪些方法可以安全地打开新窗口? [^1]: 非用户直接触发的弹窗会被浏览器安全机制拦截 [^2]: 先打开空白窗口再重定向可绕过拦截 [^3]: 必须将 `window.open` 直接绑定在用户事件上 [^4]: 异步操作后修改窗口地址是有效解决方案 [^5]: 表单提交属于浏览器白名单操作
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值