jQuery跨域ajax:执行时回调

fie*_*edl 7 ajax jquery callback cross-domain same-origin-policy

背景

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

有一个代码位需要被执行后,来自其他服务器的代码已被执行,否则某些对象"未定义",然而,.

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

没工作:success回调

显然,一个success回调的远程代码laoded后调用,但之前是远程代码执行.

# 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.
Run Code Online (Sandbox Code Playgroud)

不工作: 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)
Run Code Online (Sandbox Code Playgroud)

不工作: $.when(...).then(...)

显然,使用jQuery的when-then机制,then代码在执行when块之前执行.

# 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)
Run Code Online (Sandbox Code Playgroud)

编辑:工作,但无法使用: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)
)
Run Code Online (Sandbox Code Playgroud)

要避免的事情

我不想使用像几个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
)
Run Code Online (Sandbox Code Playgroud)

有线索吗?

有人知道在执行远程代码后我如何执行该executeLater方法?谢谢!

编辑:同源政策

正如adeneo在评论部分指出的那样,JavaScript的同源政策可能就是问题所在.

我加载ajaxgetScript调用的脚本不允许从远程服务器加载和执行另一个脚本,以防止恶意脚本"回家".

以下实验支持此功能:

这不起作用:

<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>
Run Code Online (Sandbox Code Playgroud)

这有效:

根据此stackexchange答案,同源策略允许由html <script>标记加载的远程脚本通过加载其他远程脚本ajax.

<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>
Run Code Online (Sandbox Code Playgroud)

问题仍然存在:使用ajax调用是否有一个好的方法,或者,我是否必须通过<script>在html文档中插入标记来"证明"我"拥有此代码" ?

Ahm*_*man 0

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

  1. 准备一份表格,其中包含actionmethod适合您尝试提出的请求。
  2. target将表单的( https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form )设置为指向iframe页面上的 ,这iframe可以隐藏。
  3. 听一下 的声音onloadiframeiframe加载完毕后,您就可以执行您的代码了。

这是一个小例子(使用 jQuery):

<form id="xform" action="http://foo.bar/foo/bar" method="get" target="xiframe">
  <input type="text" name="foo" value="bar" />
</form>
<iframe name="xiframe" id="xiframe"></iframe>
<script>
  var form = $('#xform'),
      iframe = $('#xiframe');

  iframe.load(function () {
    // run your stuff here
  });

  form.submit();
</script>
Run Code Online (Sandbox Code Playgroud)