JSONP

JSONP 是一种无需考虑跨域问题即可传送 JSON 数据的方法。

JSONP 不使用 XMLHttpRequest 对象。

JSONP 使用 <script> 标签取而代之。


JSONP 简介

JSONP 指的是 JSON with Padding。

从另一个域请求文件会引起问题,由于跨域政策。

从另一个域请求外部脚本没有这个问题。

JSONP 利用了这个优势,并使用 script 标签替代 XMLHttpRequest 对象。

  1. <script src="demo_jsonp.php">
Server 文件

服务器上的文件在函数调用中封装结果:

  1. <?php $myjson='{ "name":"埃隆 马斯克", "age":50, "city":"洛杉矶" }' ;="" echo="" "myfunc(".$myjson.");";=""?>

结果返回对名为 "myFunc" 的函数的调用,其中的 JSON 数据为参数。

请确保客户端存在该函数。

JavaScript 函数

函数 "myFunc" 位于客户端,用于处理 JSON 数据:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>使用 script 标签请求 JSON</h1>
  5. <p>PHP 文件所返回的函数调用处理的是 JSON 数据。</p>
  6. <p id="demo">
  7. <script>
  8. function myFunc(myObj) {
  9. document.getElementById("demo").innerHTML = myObj.name;
  10. }
  11. </script>
  12. <script src="/demo/demo_php_jsonp.php"></script>
  13. </body>
  14. </html>

创建动态脚本标签

上例会在页面加载时执行 "myFunc" 函数,根据您放置脚本标签的位置,这样不很令人满意。

Script 只应该在需要时创建:

在按钮被点击时创建和插入 <script> 标签:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>点击按钮</h1>
  5. <p>将创建一个带有 src 属性的 script 标签并将其放在文档中。</p>
  6. <p>PHP 文件以 JSON 对象作为参数返回对函数的调用。</p>
  7. <button onclick="clickButton()">单击我!</button>
  8. <p id="demo">
  9. <script>
  10. function clickButton() {
  11. var s = document.createElement("script");
  12. s.src = "/demo/demo_php_jsonp.php";
  13. document.body.appendChild(s);
  14. }
  15. function myFunc(myObj) {
  16. document.getElementById("demo").innerHTML = myObj.name;
  17. }
  18. </script>
  19. </body>
  20. </html>

动态 JSONP 结果

上例仍然是静态的。

可通过向 PHP 文件发送 JSON 来创建动态的例子,然后根据这个 php 文件获得的信息让它返回一个 JSON 对象。

PHP 文件
  1. <?php
  2. header("Content-Type: application/json; charset=UTF-8");
  3. $obj = json_decode($_GET["x"], false);
  4. $conn = new mysqli("myServer", "myUser", "myPassword", "Northwind");
  5. $result = $conn->query("SELECT name FROM ".$obj->$table." LIMIT ".$obj->$limit);
  6. $outp = array();
  7. $outp = $result->fetch_all(MYSQLI_ASSOC);
  8. echo "myFunc(".json_encode($outp).")";
  9. ?>
PHP 文件解释:

把请求转换为对象,使用 PHP 函数 json_decode()。

访问数据库,并用被请求的数据填充数组。

向对象添加数组。

使用 json_decode() 函数把该数组转换为 JSON。

用 "myFunc()" 封装返回对象。

JavaScript 实例

将从 php 文件调用 "myFunc" 函数:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>点击按钮</h1>
  5. <p>将创建一个带有 src 属性的 script 标签并将其放在文档中。</p>
  6. <p>PHP 文件以 JSON 对象作为参数返回对函数的调用。</p>
  7. <button onclick="clickButton()">单击我!</button>
  8. <p id="demo">
  9. <p>请尝试将 table 属性从“customers”更改为“products”。</p>
  10. <script>
  11. function clickButton() {
  12. var obj, s
  13. obj = { table: "customers", limit: 10 };
  14. s = document.createElement("script");
  15. s.src = "/demo/demo_php_jsonp_db.php?x=" + JSON.stringify(obj);
  16. document.body.appendChild(s);
  17. }
  18. function myFunc(myObj) {
  19. var x, txt = "";
  20. for (x in myObj) {
  21. txt += myObj[x].name + "<br>";
  22. }
  23. document.getElementById("demo").innerHTML = txt;
  24. }
  25. </script>
  26. </body>
  27. </html>

回调函数

如果您无法控制服务器文件,那么如何使服务器文件调用正确的函数呢?

有时服务器文件提供回调函数作为参数:

PHP 文件会调用您作为回调参数传递的函数:

  1. <!DOCTYPE html>
  2. <html>
  3. <body>
  4. <h1>请求调用函数</h1>
  5. <p>PHP 文件返回对您作为回调发送的函数的调用。</p>
  6. <button onclick="clickButton()">单击我!</button>
  7. <p id="demo">
  8. <script>
  9. function clickButton() {
  10. var s = document.createElement("script");
  11. s.src = "demo_jsonp2.php?callback=myDisplayFunction";
  12. document.body.appendChild(s);
  13. }
  14. function myDisplayFunction(myObj) {
  15. document.getElementById("demo").innerHTML = myObj.name;
  16. }
  17. </script>
  18. </body>
  19. </html>