JSONP是否进行异步调用?

时间:2012-02-19 12:40:31

标签: javascript asynchronous jsonp

我是jsonp的新手,我知道JSONP是一种创造动态的技术  <script src="...">标记,它使用回调函数包装返回的JavaScript(或JSON对象)。

但是,如果我没有弄错,脚本标记中的src属性将阻止所有进一步的执行,直到脚本加载,那么它怎么可以是异步调用呢?

7 个答案:

答案 0 :(得分:6)

实际上,在DOM加载完成后,您可以在herehere动态创建的<script src="..">元素上阅读不会被阻塞,因此它们将是asynchrounus .. at至少按照它们的创建顺序。

来自http://calendar.perfplanet.com/2010/the-truth-about-non-blocking-javascript/

  

动态插入脚本时,立即开始非阻塞下载。该脚本在完全下载后立即执行。在大多数浏览器中,不保证执行的顺序,尽管Firefox&lt; 4,Opera将按照插入顺序执行脚本。所有主流浏览器都支持这种通用方法。

答案 1 :(得分:3)

我认为你的问题有两个部分。

首先,JSONP本质上不是关于动态脚本标记,而是动态脚本标记是与JSONP一起使用的技术。

JSONP是一种允许站点从ORIGIN以外的不同域加载内容的方法,利用浏览器对SCRIPT标记的容忍度,src指向外部域。 (你应该通过浏览其他答案中给出的链接来了解这一点。)

另一方面,动态SCRIPT标记为JSONP或其他任何脚本提供异步性质。

重点是,只要浏览器访问文档上的SCRIPT标记,它就会停止大多数其他活动(特别呈现DOM),直到下载该脚本为止。这会影响用户对网站响应速度的体验。如果脚本没有直接影响网站的主要内容(例如Google广告,推文或Facebook时间线(假设您不是Mark Z.:P)等),则效果会更差。

为避免此问题,您可以在浏览器上完全加载动态SCRIPT标记后将其注入页面(即就绪/加载事件)。然后浏览器将静默加载新脚本,但用户已经(几乎)为他呈现了整页(给出了快速加载的印象)。从这个意义上讲,动态脚本可以与页面加载异步。

但是,实际上,以这种方式使用的大多数脚本都是驻留在不同域上的JSONP脚本,尽管这不是必需的。

希望这是有道理的。

对于TRUE异步脚本加载,您应该查看HTML5 sync属性:

答案 2 :(得分:2)

呼叫是异步的,是的。也许在页面加载和页面加载时,您会混淆脚本标记的行为。

当浏览器加载页面时,所有带有资源的HTML标签(图像标签,链接标签等)都会异步下载资源,不会中断浏览器渲染任务。这有改进优化页面呈现的性能。

唯一不遵循此规则的标记是脚本标记。因为浏览器必须确保脚本的顺序,所以它不会并行加载它们。此外,浏览器必须使用document.write对脚本生成的HTML文档进行动态更改,因此它将在下载后立即对脚本进行评估。因此,这是浏览器关于带有src文件的脚本标记的默认行为:它们将阻止页面的呈现,按顺序下载并在加载后立即进行评估。有一些技术可以避免这种情况,例如将脚本放在文档的底部(脚本只会在文档呈现后下载和评估)或使用新的HTML5脚本标记属性“async”和“defer”:{{ 3}}。

回到JSONP:是的,它是异步的,它没有阻止任何进一步的浏览器行为(页面已经呈现)。这是常规AJAX调用提供的异步性。

答案 3 :(得分:1)

JSONp包括不像AJAX调用那样真正起作用,因为它们有点像黑客。如果我被迫把它们放在任何一个盒子里,我会选择“异步”。

我猜最重要的特质是'返回值'会出现在另一个事件中。

你不能写:

var return_value = do_jsonp("my function");

你必须改为:(或使用某种承诺库)

do_jsonp("my function", function (return_value) {});

因此,当JSONp资源中的脚本实际执行时不相关。所有相关的是它发生在不同的事件中。

答案 4 :(得分:0)

This相关问题应该可以解释您的问题。

使用javascript动态添加的脚本节点是异步执行的,它们不会阻止其他脚本的执行。

答案 5 :(得分:0)

你有点误解“异步”这个词。 javascript执行是异步的,这意味着执行注入脚本标记后出现的每一行javascript代码。

示例:

var yourCB = function(result) { ... }

// i use the script injection from neiker here (without the async = true, to illustrate that this has nothing to do with the asynchronous nature JSONP 
var ga = document.createElement('script'); 
ga.type = 'text/javascript'; 
ga.src = 'http://domain/api/...?callback=yourCB';
var s = document.getElementsByTagName('script')[0]; 
s.parentNode.insertBefore(ga, s);

// everything after the script insertion is excecuted, even if your jsonp-callback hasnt been called. as soon as your script-request has finished yourCB is called.
alert('THIS IS ALERTED EVEN IF yourCB HASNT BEEN CALLED');

答案 6 :(得分:-2)

var ga = document.createElement('script'); 
ga.type = 'text/javascript'; 
ga.async = true;
ga.src = 'http://domain/api/...?callback=something';
var s = document.getElementsByTagName('script')[0]; 
s.parentNode.insertBefore(ga, s);

无论如何,你不能使用jQuery吗?如果没有,请尝试:https://github.com/ded/reqwest