24.4.2JSONP
JSONP 是“JSON with padding”的简写,是在 Web 服务上流行的一种 JSON 变体。JSONP 看起来 跟 JSON 一样,只是会被包在一个函数调用里,比如:
callback({ name: "Nicholas" });
JSONP 格式包含两个部分:回调和数据。回调是在页面接收到响应之后应该调用的函数,通常回调
函数的名称是通过请求来动态指定的。而数据就是作为参数传给回调函数的 JSON 数据。
下面是一个典型的 JSONP
请求:
http://freegeoip.net/json/?callback=handleResponse
这个 JSONP 请求的 URL 是一个地理位置服务。JSONP 服务通常支持以查询字符串形式指定回调函
数的名称。比如这个例子就把回调函数的名字指定为 handleResponse()
。
JSONP 调用是通过动态创建<script>
元素并为 src 属性指定跨域 URL 实现的。此时的<script>
与<img>
元素类似,能够不受限制地从其他域加载资源。因为 JSONP 是有效的 JavaScript,所以 JSONP
响应在被加载完成之后会立即执行。比如下面这个例子:
function handleResponse(response) {
console.log(`
You're at IP address ${response.ip}, which is in
${response.city}, ${response.region_name}`);
}
let script = document.createElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);
这个例子会显示从地理位置服务获取的 IP 地址及位置信息。
JSONP 由于其简单易用,在开发者中非常流行。相比于图片探测,使用 JSONP 可以直接访问响应, 实现浏览器与服务器的双向通信。不过 JSONP 也有一些缺点。
JSONP 是从不同的域拉取可执行代码。如果这个域并不可信,则可能在响应中加入恶意内容。 此时除了完全删除 JSONP 没有其他办法。在使用不受控的 Web 服务时,一定要保证是可以信任的。
第二个缺点是不好确定 JSONP 请求是否失败。虽然 HTML5 规定了
<script>
元素的 onerror 事件 处理程序,但还没有被任何浏览器实现。为此,开发者经常使用计时器来决定是否放弃等待响应。这种 方式并不准确,毕竟不同用户的网络连接速度和带宽是不一样的。