jQuery跨域ajax:执行时回调

时间:2013-09-12 22:41:25

标签: jquery ajax callback cross-domain same-origin-policy

背景

我正在通过jQuery的.ajax(...)调用从另一台服务器(跨域)加载并执行脚本。

其他服务器的代码执行之后,需要执行一些代码,因为否则某些对象“未定义”。

可能很重要:远程代码确实包含另一个getScript(...)来电。而且我必须等待这个代码也被执行。我不能简单地从我的代码加载第二个脚本,因为它的源是动态的(即取决于远程脚本的某些结果)。

无效:success回拨

显然,在远程代码加密后会调用success回调,但之前远程代码执行

# coffee script

executeLater = ->
  # this bit of code needs to run after the remote code has been executed.
  console.log("yehaa!")

$.getScript("http://example.com/script-from-other-server.js")
.success(executeLater)  # this gets executed when the remote script is loaded,
                        # but before the remote script is executed.

无效:async: false

显然,对于跨域请求,async属性会被忽略,如jQuery文档中所述:http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings

此外,我想避免async: false设置,因为据说它会阻止浏览器。

# coffee script

executeLater = ->
  # this bit of code needs to run after the remote code has been executed.
  console.log("yehaa!")

$.ajax(
  dataType: 'script',
  url: 'http://example.com/script-from-other-server.js',
  async: false   # does not work because the request is cross domain
)
.success(executeLater)

无效:$.when(...).then(...)

使用jQuery的when-then mechanism,显然,{strong} 之前执行<{1}}代码执行

then

编辑:有效但无法使用:# coffee script executeLater = -> # this bit of code needs to run after the remote code has been executed. console.log("yehaa!") $.when( $.ajax( dataType: 'script', url: 'http://example.com/script-from-other-server.js', ) ).then(executeLater) 两个脚本

我不能在生产中这样做,正如我在上面的“背景”部分所述,但如果我将所有情况减少到一个并加载第二个脚本(通常由远程脚本执行),在我自己的脚本中一切正常。

ajax

要避免的事情

我不想使用像# coffee script executeLater = -> # this bit of code needs to run after the remote code has been executed. console.log("yehaa!") $.getScript("http://example.com/script-from-other-server.js") .success( -> $.ajax( dataType: 'script', cache: true, # I do not know this url in production: url: 'http://example.com/another-script-from-the-remote-server.js' ) .success(executeLater) ) 个调用这样的构造,直到某个对象被定义为执行setTimout方法。

我需要的是:executeLater()回调

使用executed回调而不是executed方法的success回调是完美的。但是,到目前为止,我还没有找到这个回调。

ajax

任何线索?

有人知道在执行远程代码后如何执行# coffee script executeLater = -> # this bit of code needs to run after the remote code has been executed. console.log("yehaa!") $.ajax( dataType: 'script', url: 'http://example.com/script-from-other-server.js', executed: executeLater # <---- I NEED A CALLBACK LIKE THIS ) 方法 ?谢谢!

编辑:同源政策

正如 adeneo 在评论部分中指出的那样,JavaScript的same-origin policy可能就是问题所在。

我使用executeLaterajax调用加载的脚本不允许从远程服务器加载和执行另一个脚本,以防止恶意脚本“回家”。

以下实验支持此功能:

这不起作用:

getScript

这有效:

根据this stackexchange answer,同源策略允许由html <html><head> <script language="javascript" src="http://code.jquery.com/jquery-1.10.2.js"></script> <script language="javascript"> jQuery.getScript("http://example.com/script-from-other-server.js") </script> </head><body></body></html> 标记加载的远程脚本通过<script>加载其他远程脚本。

ajax

问题仍然存在:使用ajax调用是否有好方法,或者,我必须通过插入{{1}来“证明”我“拥有此代码”标记到html文档?

2 个答案:

答案 0 :(得分:2)

背景

adeneo建议考虑 JavaScripts同源政策(请参阅问题评论)确实解决了我的问题。

如果问题假定在请求的脚本完全执行之前调用了success回调,那么真正的问题是,请求的脚本确实请求了另一个脚本,如问题中所述:

  

可能很重要:远程代码确实包含另一个getScript(...)调用。而且我必须等待这个代码也被执行。我不能简单地从我的代码加载第二个脚本,因为它的源是动态的(即取决于远程脚本的某些结果)。

当动态加载请求的脚本时,JavaScript的同源策略会阻止第二次getScript调用。

解决方案1:在html代码中包含脚本

如果有权访问html文件,可以添加脚本标记,远程脚本为src。因此,一个&#34;证明&#34;那个人真的想加载这个远程脚本,javascript将执行远程getScript调用。

<html><head>
  ...
  <script language="javascript" src="http://code.jquery.com/jquery-1.10.2.js"></script>
  <script language="javascript" src="http://example.com/script-from-other-server.js"></script>
</head><body></body></html>

为了执行executeLater代码,可以简单地使用ready回调:

# coffee script

executeLater = ->
  # this bit of code needs to run after the remote code has been executed.
  console.log("yehaa!")

$(document).ready(executeLater)

解决方案2:规避某些来源政策

不建议这样做,但可以。 有一个流行的堆栈溢出问题如何绕过同源策略:

Ways to circumvent the same-origin policy

解决方案3:真的等待脚本执行

如果除了同源策略之外,远程脚本真的需要很长时间才能执行,本地脚本必须等待它,可以使用Ahmed Nuaman的iframe解决方案:

https://stackoverflow.com/a/18793000/2066546

答案 1 :(得分:0)

这有点讨厌,但您尝试使用iframe吗?这个想法很简单:

  1. 制作一张表格,actionmethod适合您正在尝试的请求。
  2. 将表单的targethttps://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)设置为指向您网页上的iframe,可以隐藏此iframe
  3. 聆听onload的{​​{1}},加载iframe后,即可执行您的代码。
  4. 所以这是一个小例子(使用jQuery):

    iframe