当调用框架(和执行上下文)消失时处理回调
让我们假设您有两个框架,A 和 B(或带有 iframe 的页面)。 A 中有一个函数 foo()
,完成后会调用回调。 B 中的脚本从 A 调用 foo()
,但在完成之前(并从 B 调用回调),B 的 src 被完全替换,因此回调不再具有执行上下文。在大多数浏览器中,这会产生某种错误。
有什么方法可以检测回调来自不再具有执行上下文的运行时,因此不应被调用?
这是包装页:
<html>
<head>
<script>
var load = function() {
document.getElementById("link").onclick = function(){
document.getElementById("iframe").src = "test-exec-context-frame-src.html";
return(false);
};
};
var frameLoad = function(cb) {
// kill the frame and then callback
document.getElementById("iframe").src = "http://www.google.com";
cb();
};
</script>
</head>
<body onload="load();">
<div>This is the first div, click <a id="link" href="#">here</a> to start</div>
<iframe id="iframe"></iframe>
</body>
这是 iframe src 页面:
<html>
<head>
<script>
var load2 = function() {
document.getElementById("link").onclick = function(){
top.frameLoad(function(){
console.log("I am done");
});
};
};
</script>
</head>
<body onload="load2();">
<div>This is the internal frame. Click <a href="#" id="link">here</a> to force the callback.</div>
</body>
单击第一页中的链接,iframe 将加载第二个源页面。单击第二页中的链接,它会通过回调调用 top.frameLoad 。在运行回调之前,iframe src 会更改为 www.google.com,从而破坏回调的执行上下文。回调运行并产生错误。
在尝试执行回调之前,我们如何检查回调的执行上下文(或者可能是调用函数的执行上下文)?
(忽略格式、全局变量的使用、jquery 比 document.getElementById 更好地处理它的事实等。这只是一个测试。)
Let us assume you have two frames, A and B (or a page with an iframe). A has a function foo()
in it that, when complete, calls a callback. A script in B calls foo()
from A, but before it completes (and calls the callback from B), B's src is replaced entirely, so that the callback no longer has an execution context. In most browsers, this will generate some sort of error.
Is there any way to detect that the callback is from a runtime that no longer has execution context, and thus should not be called?
Here is the wrapping page:
<html>
<head>
<script>
var load = function() {
document.getElementById("link").onclick = function(){
document.getElementById("iframe").src = "test-exec-context-frame-src.html";
return(false);
};
};
var frameLoad = function(cb) {
// kill the frame and then callback
document.getElementById("iframe").src = "http://www.google.com";
cb();
};
</script>
</head>
<body onload="load();">
<div>This is the first div, click <a id="link" href="#">here</a> to start</div>
<iframe id="iframe"></iframe>
</body>
And here is the iframe src page:
<html>
<head>
<script>
var load2 = function() {
document.getElementById("link").onclick = function(){
top.frameLoad(function(){
console.log("I am done");
});
};
};
</script>
</head>
<body onload="load2();">
<div>This is the internal frame. Click <a href="#" id="link">here</a> to force the callback.</div>
</body>
Click on the link in the first page, the iframe is loaded with the second source page. Click on the link in the second page, it calls top.frameLoad with a callback. Before the callback is run, the iframe src gets changed to www.google.com, destroying the execution context for the callback. The callback is run and creates an error.
How can we check the execution context of the callback - or perhaps of the calling function - before attempting to execute the callback?
(Ignore the formatting, use of global vars, the fact that jquery would handle it better than document.getElementById, etc. This is just a test.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不知道如何检查执行上下文是否消失,但我想到的两个解决方法是:
将回调调用放入 try/catch 并忽略任何异常。
在与
frameLoad
函数相同的框架中定义回调函数,这样从 iframe 中对frameLoad
的调用将如下所示:top.frameLoad( top.someCallbackFunction);
如果您知道
frameLoad
函数的全部要点是替换定义回调的 iframe 的内容,那么为什么到底使用回调吗?任何重要的回调都会想要与原始内容进行交互,不是吗?您可以通过在最初位于 iframe 内的文档中定义onunload
来实现类似的效果吗?更新:
当我建议 try/catch 时,我的意思是在您的父文档脚本中像这样:
您也可以尝试
if (cb != undefined) cb();
或类似的。I don't know how to check if the execution context is gone, but two workarounds that occur to me are:
Put the callback call in a try/catch and ignore any exception.
Define the callback function in the same frame as your
frameLoad
function so then from the iframe your call toframeLoad
will look like this:top.frameLoad(top.someCallbackFunction);
If you know the whole point of the
frameLoad
function is to replace the contents of the iframe that defines the callback then why use a callback at all? Any non-trivial callback is going to want to interact with the original content isn't it? Could you achieve something similar by defining anonunload
in the document that was originally within the iframe?UPDATE:
When I suggested a try/catch I meant in your parent document script like this:
You could also try
if (cb != undefined) cb();
or similar.