7

背景

我正在通过 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 机制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)

编辑:确实有效,但无法使用: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
)

有什么线索吗?

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

编辑:同源政策

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

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

以下实验支持这一点:

这不起作用:

<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>

这有效:

根据this stackexchange answer,同源策略允许由 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>

问题仍然存在:有没有一种通过 ajax 调用来做到这一点的好方法,或者,我是否必须通过<script>在 html 文档中插入标签来“证明”我“拥有这段代码”?

4

2 回答 2

2

背景

adeneo 建议考虑JavaScripts Same-Origin Policy(请参阅问题的评论)确实解决了我的问题。

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

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

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

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

如果可以访问 html 文件,则可以添加一个带有远程脚本的脚本标记为src. 因此,一个人“证明”了一个人真的想要加载这个远程脚本,而 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:规避 some-origin 策略

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

规避同源政策的方法

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

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

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

于 2013-09-17T23:49:04.760 回答
0

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

  1. 有一个适合您尝试提出的请求action的表格。method
  2. 将表单的target( https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form ) 设置为指向iframe页面上的一个,这iframe可以隐藏。
  3. onloadiframe并且当iframe加载时你可以执行你的代码。

所以这里有一个小例子(使用 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>
于 2013-09-13T18:35:34.217 回答