1. 1. 什么是jsonp
    1. 1.1. 从零开始构建
    2. 1.2. 版本一
      1. 1.2.1. server001.js
        1. 1.2.1.1. index.html
        2. 1.2.1.2. 运行 server001.js 所在目录 打开命令行运行
        3. 1.2.1.3. 问题1 每次点击按钮都会把余额减1 但是浏览器只要刷新就会重新显示100
        4. 1.2.1.4. 长久的保存用户数据 保存到文件里
    3. 1.3. 版本二
      1. 1.3.0.1. 修改html里写死的100 换用一个‘匹配’字符替换 ==> “&&&amount&&&”
      2. 1.3.0.2. 解决长久保存
    4. 1.3.1. 为什么不是get 付款啊!这么重要的操作你敢用get?
  2. 1.4. 版本三
    1. 1.4.0.1. index003.html
    2. 1.4.0.2. server003.js
    3. 1.4.0.3. 再去开启你的服务器
    4. 1.4.0.4. 以上就是最最简单、最最原始的数据库的展示
    5. 1.4.0.5. 再次修改一下server003.js里的代码
  3. 1.4.1. 以上是:旧时代的前后端配合
  4. 1.4.2. 在一个2018年的今天
  5. 1.4.3. form表单一旦提交不管成功还是失败一定会刷新当前页面
  6. 1.4.4. 古老方式-优化一下用户体验
  • 1.5. 版本四
    1. 1.5.0.1. index004.html
    2. 1.5.0.2. 前端的高度洁癖 不用form向后台发送一个请求
  • 1.6. 版本五
    1. 1.6.0.1. index005.html
    2. 1.6.0.2. 这样的缺陷就是 它无法post 它只能get
    3. 1.6.0.3. 问题来了? 我们如何知道它成功or失败呢?
    4. 1.6.0.4. server005.js
    5. 1.6.0.5. 这样我们就完成了 无刷新的发送请求 俗称 image发请求法
  • 1.6.1. 改良 script发请求法
    1. 1.6.1.1. 注意动态创建script 同时设置src 必须把script添加到body里才会生效
  • 1.7. 版本六
    1. 1.7.0.1. server006.js
    2. 1.7.0.2. index006.html
    3. 1.7.0.3. 我们知道 script里的代码是会执行的
    4. 1.7.0.4. step1修改server006.js
    5. 1.7.0.5. 不用监听script.onload了
  • 1.8. 版本七
    1. 1.8.0.1. index007.html
    2. 1.8.0.2. server007.js
    3. 1.8.0.3. 优化上面运行后每次点击按钮页面都会多一个script标签
  • 1.9. 版本八
    1. 1.9.0.1. index008.html
    2. 1.9.0.2. 注意:不管成功还是失败script都会移除 但是script还在内存里只是从页面移除了
    3. 1.9.0.3. 这个方案就叫 SRJ (Server rendered javascript)服务器返回的 javascript
  • 1.9.1. script是不受域名限制的 这跟跨域没关系
  • 1.9.2. JSONP
    1. 1.9.2.1. 查看后端代码 发现– 后端要对前端代码非常了解
    2. 1.9.2.2. 耦合
    3. 1.9.2.3. 解耦
  • 1.10. 版本九
    1. 1.10.0.1. index009.html
    2. 1.10.0.2. server009.js
  • 1.10.1. 这样的好处是什么
    1. 1.10.1.1. xxx.call()是不是很丑?
  • 1.11. 版本十
    1. 1.11.0.1. index010.html
    2. 1.11.0.2. server010.js
    3. 1.11.0.3. JSONP解决的问题是什么 两个网站之间如何交流
    4. 1.11.0.4. 传递的参数不仅仅是字符串还可以是json
  • 1.12. 版本十一
    1. 1.12.1. index011.html
    2. 1.12.2. server011.js
      1. 1.12.2.1. 写了那么多 其实你可以使用jQuery 几句话就能搞定
      2. 1.12.2.2. 注意: $.ajax()只是把jsonp归纳到 jq里 而它不是ajax
    3. 1.12.3. 考点1 :请问JSONP为什么不支持POST请求
    4. 1.12.4. 考点2 : 什么是 JSONP?
  • JSONP是什么鬼

    什么是jsonp

    从零开始构建

    1
    2
    3
    4
    mkdir jsonp_demo  //创建目录 jsonp_demo
    cd jsonp_demo //切换目录到 json_demo
    touch server001.js
    touch index001.html

    版本一

    server001.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    var http = require('http')
    var fs = require('fs')
    var url = require('url')
    var port = process.argv[2]

    if(!port){
    console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
    process.exit(1)
    }

    var server = http.createServer(function(request, response){
    var parsedUrl = url.parse(request.url, true)
    var pathWithQuery = request.url
    var queryString = ''
    if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
    var path = parsedUrl.pathname
    var query = parsedUrl.query
    var method = request.method

    /******** 从这里开始看,上面不要看 ************/

    console.log('被请求后:含查询字符串的路径\n' + pathWithQuery)

    if(path=='/'){
    var string = fs.readFileSync('./index001.html','utf8');
    response.setHeader('Content-Type','text/html;charset=utf-8');
    response.write(string);
    response.end();
    }else{
    response.statusCode = 404;
    response.end();
    }

    /******** 代码结束,下面不要看 ************/
    })

    server.listen(port)
    console.log('监听 ' + port + ' 成功\n请在浏览器输入 http://localhost:' + port)

    当前目录下 新建index.html main.js style.css (main.js/style.css内容为空暂时不需要)

    index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="./style.css">
    <title>Document</title>
    </head>
    <body>
    <h5>您的账户余额是 <span id="amount">100</span> </h5>
    <button id="btn">付款1块钱</button>
    <script src="./main.js"></script>
    <script>
    btn.addEventListener('click',()=>{
    let n = amount.innerText;
    let number = parseInt(n,10);
    let newNumber = number - 1;
    amount.innerText = newNumber;
    })
    </script>
    </body>
    </html>

    运行 server001.js 所在目录 打开命令行运行

    1
    2
    3
    4
    node server001.js 9999
    //你会看到
    监听 9999 成功
    请在浏览器输入 http://localhost:9999

    打开浏览器输入 http://localhost:9999

    运行后

    点击按钮后你会看到 余额变动如下

    点击付款

    问题1 每次点击按钮都会把余额减1 但是浏览器只要刷新就会重新显示100

    如何长久的保存用户的数据呢?不可能你的余额永远是100吧 那岂不是有花不完的钱

    长久的保存用户数据 保存到文件里

    文件系统 将数据保存到服务器的文件里 这个文件专门为这个用户服务

    1
    2
    3
    touch db //创建 db 文件  

    vi db //打开之后写入100

    版本二

    修改html里写死的100 换用一个‘匹配’字符替换 ==> “&&&amount&&&”

    index002.html

    1
    2
    3
    4
    5
    //将这一行
    <h5>您的账户余额是 <span id="amount">100</span> </h5>
    //修改为
    //自己定义替换的匹配字符串 "&&&amount&&&"
    <h5>您的账户余额是 <span id="amount"> &&&amount&&&</span> </h5>

    server002.js 修改如下内容 从db读取 用户余额

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if(path=='/'){
    var string = fs.readFileSync('./index002.html','utf8');
    //读取db文件里用户余额
    var amount = fs.readFileSync('./db','utf8'); //100
    //替换 index002.html 里定义的 匹配字符 为 用户余额
    string = string.replace('&&&amount&&&',amount);
    response.setHeader('Content-Type','text/html;charset=utf-8');
    response.write(string);
    response.end();
    }

    这样做了之后你会发现 一刷新 数据还是100

    解决长久保存

    我们点击付款的时候 告诉服务器 请把数据库里的余额给我

    所以我们点击付款的时候不能单独修改本地了 要去给服务器发 post请求

    为什么不是get 付款啊!这么重要的操作你敢用get?

    版本三

    index003.html

    1
    2
    3
    4
    <h5>您的账户余额是 <span id="amount">&&&amount&&&</span></h5>
    <form action="/pay" method="post">
    <input type="submit" value="付款1块钱">
    </form>

    server003.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    if(path=='/'){
    var string = fs.readFileSync('./index003.html','utf8');
    var amount = fs.readFileSync('./db','utf8'); //100
    string = string.replace('&&&amount&&&',amount);
    response.setHeader('Content-Type','text/html;charset=utf-8');
    response.write(string);
    response.end();
    }else if(path=='/pay'&& method.toUpperCase() === 'POST'){
    //读取 db中用户余额
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1; //余额减1
    fs.writeFileSync('./db',newAmount); //更新余额
    response.write('success');
    response.end();
    }else{
    response.statusCode = 404;
    response.end();
    }

    再去开启你的服务器

    1
    2
    node server003.js 9999
    //在浏览器打开 http://localhost:9999

    http://localhost:9999

    • 点击付款按钮
    • 跳到 http://localhost:9999/pay 页面显示 success
    • 点击浏览器返回 **注意:此时浏览器返回的是缓存页面 你要手动刷新一下
    • 用户余额减少了

    你去打开db文件 发现余额改变了

    以上就是最最简单、最最原始的数据库的展示

    再次修改一下server003.js里的代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    else if(path=='/pay'&& method.toUpperCase() === 'POST'){
    //读取 db中用户余额
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1; //余额减1
    if(Math.random()>0.5){
    fs.writeFileSync('./db',newAmount); //更新余额
    response.write('success');
    }else{
    response.write('fail');
    }

    response.end();
    }

    以上是:旧时代的前后端配合

    操作数据库成功返回success 失败返回fail

    在一个2018年的今天

    用户怎么可能忍受

    • 点击付款
    • 进入成功/失败页面
    • 点击返回
    • 点击刷新才看到你最新的数据

    form表单一旦提交不管成功还是失败一定会刷新当前页面

    古老方式-优化一下用户体验

    用iframe承载这个form的提交 后的 success/fail响应 但是I现在已经没人用啦!

    版本四

    index004.html

    1
    2
    3
    4
    5
    6
    7
    <body>
    <h5>您的账户余额是 <span id="amount">&&&amount&&&</span></h5>
    <form action="/pay" method="post" target="result">
    <input type="submit" value="付款1块钱">
    </form>
    <iframe name="result" src="about:blank" frameborder="0"></iframe>
    </body>

    前端的高度洁癖 不用form向后台发送一个请求

    版本五

    index005.html

    1
    2
    3
    4
    5
    6
    7
    8
    <h5>您的账户余额是 <span id="amount">&&&amount&&&</span></h5>
    <button id="btn">打钱</button>
    <script>
    btn.addEventListener('click',function(){
    let img = document.createElement('img');
    img.src = '/pay';
    })
    </script>

    点击按钮的时候 会创建一个img标签 设置它的 src = ‘你的请求路径’ 就会触发请求

    这样的缺陷就是 它无法post 它只能get

    问题来了? 我们如何知道它成功or失败呢?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <h5>您的账户余额是 <span id="amount">&&&amount&&&</span></h5>
    <button id="btn">打钱</button>
    <script>
    btn.addEventListener('click',function(){
    let img = document.createElement('img');
    img.src = '/pay';
    //我们如何知道请求成功or失败呢?
    img.onload = function(){
    alert('打钱成功')
    //我们帮用户刷新 但是会重绘整个页面
    //window.location.reload();
    //因为知道固定减1 所以我帮用户减1
    amount.innerText = amount.innerText - 1;
    }
    img.onerror = function(){
    alert('打钱失败')
    }
    })
    </script>

    server005.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    else if(path=='/pay'){
    //读取 db中用户余额
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1; //余额减1
    if(Math.random()>0.5){
    fs.writeFileSync('./db',newAmount); //更新余额
    //设置响应头
    response.setHeader('Content-Type','image/png');
    //设置状态码
    response.statusCode = 200;
    //返回响应的图片 不然 会走入img.onerror 事件里
    response.write(fs.readFileSync('./dog.jpg'));
    }else{
    response.statusCode = 400;
    response.write('fail');
    }

    response.end();
    }

    这样我们就完成了 无刷新的发送请求 俗称 image发请求法

    改良 script发请求法

    注意动态创建script 同时设置src 必须把script添加到body里才会生效

    版本六

    server006.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    /******** 从这里开始看,上面不要看 ************/

    console.log('被请求后:含查询字符串的路径\n' + pathWithQuery)

    if(path=='/'){
    var string = fs.readFileSync('./index006.html','utf8');
    var amount = fs.readFileSync('./db','utf8'); //100
    string = string.replace('&&&amount&&&',amount);
    response.setHeader('Content-Type','text/html;charset=utf-8');
    response.write(string);
    response.end();
    }else if(path=='/pay'){
    //读取 db中用户余额
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1; //余额减1
    if(Math.random()>0.5){
    fs.writeFileSync('./db',newAmount); //更新余额
    //设置响应头
    response.setHeader('Content-Type','application/javascript');
    //设置状态码
    response.statusCode = 200;
    //返回响应内容
    response.write('');
    }else{
    response.statusCode = 400;
    response.write('fail');
    }

    response.end();
    }else{
    response.statusCode = 404;
    response.end();
    }

    /******** 代码结束,下面不要看 ************/

    index006.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <h5>您的账户余额是 <span id="amount">&&&amount&&&</span></h5>
    <button id="btn">打钱</button>
    <script>
    btn.addEventListener('click',function(){
    let script = document.createElement('script');
    script.src = '/pay';
    document.body.appendChild(script);
    //我们如何知道请求成功or失败呢?
    script.onload = function(){
    alert('打钱成功')
    }
    script.onerror = function(){
    alert('打钱失败')
    }
    })
    </script>

    这样每次点击会生成一个script

    我们知道 script里的代码是会执行的

    所以我们就不需要在 server006.js里写失败的情况 它会自动进入 script.onerror里

    step1修改server006.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    else if(path=='/pay'){
    //读取 db中用户余额
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1; //余额减1

    fs.writeFileSync('./db',newAmount); //更新余额
    //设置响应头
    response.setHeader('Content-Type','application/javascript');
    //设置状态码
    response.statusCode = 200;
    //返回响应内容
    response.write('alert("pay")');

    response.end();
    }

    运行发现如果成功了 就会 弹出pay 然后再弹出‘打钱成功’

    不用监听script.onload了

    因为 成功自然会在server006.js 里 写入并执行 response.write(‘alert(“pay”)’);

    版本七

    index007.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <h5>您的账户余额是 <span id="amount">&&&amount&&&</span></h5>
    <button id="btn">打钱</button>
    <script>
    btn.addEventListener('click',function(){
    let script = document.createElement('script');
    script.src = '/pay';
    document.body.appendChild(script);
    script.onerror = function(){
    alert('打钱失败')
    }
    })
    </script>

    server007.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    else if(path=='/pay'){
    //读取 db中用户余额
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1; //余额减1

    fs.writeFileSync('./db',newAmount); //更新余额
    //设置响应头
    response.setHeader('Content-Type','application/javascript');
    //设置状态码
    response.statusCode = 200;
    //返回响应内容
    response.write(
    `
    amount.innerText = amount.innerText - 1;
    `
    );

    response.end();

    优化上面运行后每次点击按钮页面都会多一个script标签

    成功或者失败后干掉script

    版本八

    index008.html

    注意:server里文件路径

    所以我们还是得监听onload事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <h5>您的账户余额是 <span id="amount">&&&amount&&&</span></h5>
    <button id="btn">打钱</button>
    <script>
    btn.addEventListener('click',function(){
    let script = document.createElement('script');
    script.src = '/pay';
    document.body.appendChild(script);
    script.onload = function(e){
    alert('打钱成功')
    e.currentTarget.remove();
    }
    script.onerror = function(e){
    alert('打钱失败')
    e.currentTarget.remove();
    }
    })
    </script>

    注意:不管成功还是失败script都会移除 但是script还在内存里只是从页面移除了

    这个方案就叫 SRJ (Server rendered javascript)服务器返回的 javascript

    无刷新局部更新页面内容的方案 在ajax之前

    script是不受域名限制的 这跟跨域没关系

    aa.com:9999的前端 是可以访问 bb.com:8888的后台接口的 这就是SRJ

    JSONP

    查看后端代码 发现– 后端要对前端代码非常了解

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    else if(path=='/pay'){
    //读取 db中用户余额
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1; //余额减1

    fs.writeFileSync('./db',newAmount); //更新余额
    //设置响应头
    response.setHeader('Content-Type','application/javascript');
    //设置状态码
    response.statusCode = 200;
    //返回响应内容
    response.write(
    `
    amount.innerText = amount.innerText - 1;
    `
    );

    response.end();

    bb.com:8888的后端居然要对 aa.com:9999的页面如此清楚

    耦合

    解耦

    版本九

    index009.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <h5>您的账户余额是 <span id="amount">&&&amount&&&</span></h5>
    <button id="btn">打钱</button>
    <script>
    //某域名下的前端 bb.com:9999的前端
    window.xxx = function(result){
    alert(`得到了结果是${result}`);
    }

    btn.addEventListener('click',function(){
    let script = document.createElement('script');
    script.src = '/pay';
    document.body.appendChild(script);
    script.onload = function(e){
    e.currentTarget.remove();
    }
    script.onerror = function(e){
    alert('打钱失败')
    e.currentTarget.remove();
    }
    })
    </script>

    server009.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    else if(path=='/pay'){
    //读取 db中用户余额
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1; //余额减1

    fs.writeFileSync('./db',newAmount); //更新余额
    //设置响应头
    response.setHeader('Content-Type','application/javascript');
    //设置状态码
    response.statusCode = 200;
    //返回响应内容
    response.write(
    `
    xxx.call(undefined,'success') //执行xxx方法并返回 字符串
    `
    );

    response.end();
    }

    这样的好处是什么

    • 后端不需要知道任何细节,只调用xxx.call()返回结果
    • 这样两个网站之间就可以无缝的沟通

    xxx.call()是不是很丑?

    • 于是传递一个参数callback=xxx
    • callback =’你自己定义的方法名’

    版本十

    index010.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <h5>您的账户余额是 <span id="amount">&&&amount&&&</span></h5>
    <button id="btn">打钱</button>
    <script>
    //某域名下的前端 bb.com:9999的前端
    window.yyy = function(result){
    alert(`得到了结果是${result}`);
    }

    btn.addEventListener('click',function(){
    let script = document.createElement('script');
    //传递自己定义的方法名
    script.src = '/pay?callback=yyy';
    document.body.appendChild(script);
    script.onload = function(e){
    e.currentTarget.remove();
    }
    script.onerror = function(e){
    alert('打钱失败')
    e.currentTarget.remove();
    }
    })
    </script>

    server010.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    else if(path=='/pay'){
    //读取 db中用户余额
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1; //余额减1

    fs.writeFileSync('./db',newAmount); //更新余额
    //设置响应头
    response.setHeader('Content-Type','application/javascript');
    //设置状态码
    response.statusCode = 200;
    //返回响应内容
    response.write(
    `
    ${query.callback}.call(undefined,'success')
    `
    );

    response.end();
    }

    JSONP解决的问题是什么 两个网站之间如何交流

    • 因为script是不受域名限制的 ajax是受域名限制的
    • 由于不受域名限制,我就告诉对方的网站 我要请求一个数据,
    • 请你把数据给我
    • 你给我之后调用我的xxx
    • 然后把参数给我 xxx.call(undefined,参数)

    传递的参数不仅仅是字符串还可以是json

    1
    2
    3
    4
    5
    6
    7
    8
    response.write(
    `
    ${query.callback}.call(undefined,{
    "success":true,
    "data":99
    })
    `
    );

    json

    1
    2
    3
    4
    {
    "success":true,
    "data":99
    }

    json的左边是 左padding : ${query.callback}.call(undefined,

    json的右边是 右padding : )

    于是乎 JSON + padding = JSONP

    jsonp

    版本十一

    index011.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    <h5>您的账户余额是 <span id="amount">&&&amount&&&</span></h5>
    <button id="btn">打钱</button>
    <script>
    btn.addEventListener('click',function(){
    let script = document.createElement('script');

    //生成无重复的方法名
    let fnName = 'hjx'+parseInt(Math.random()*100000,10);
    window[fnName] = function(result){
    //根据接收的json结果做处理
    if(result === 'success'){
    amount.innerText = amount.innerText - 1;
    }
    }
    //传递自己定义的方法名
    script.src = '/pay?callback=' + fnName;
    document.body.appendChild(script);
    script.onload = function(e){
    e.currentTarget.remove();
    //不管成功失败都要删除生成的fnName属性
    delete window[fnName];
    }
    script.onerror = function(e){
    alert('打钱失败')
    e.currentTarget.remove();
    //不管成功失败都要删除生成的fnName属性
    delete window[fnName];
    }
    })
    </script>

    server011.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    var http = require('http')
    var fs = require('fs')
    var url = require('url')
    var port = process.argv[2]

    if(!port){
    console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
    process.exit(1)
    }

    var server = http.createServer(function(request, response){
    var parsedUrl = url.parse(request.url, true)
    var pathWithQuery = request.url
    var queryString = ''
    if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
    var path = parsedUrl.pathname
    var query = parsedUrl.query
    var method = request.method

    /******** 从这里开始看,上面不要看 ************/

    console.log('被请求后:含查询字符串的路径\n' + pathWithQuery)

    if(path=='/'){
    var string = fs.readFileSync('./index011.html','utf8');
    var amount = fs.readFileSync('./db','utf8'); //100
    string = string.replace('&&&amount&&&',amount);
    response.setHeader('Content-Type','text/html;charset=utf-8');
    response.write(string);
    response.end();
    }else if(path=='/style.css'){
    var string = fs.readFileSync('./style.css','utf8');
    response.setHeader('Content-Type','text/css');
    response.write(string);
    response.end();
    }else if(path=='/main.js'){
    var string = fs.readFileSync('./main.js','utf8');
    response.setHeader('Content-Type','text/javascript');
    response.write(string);
    response.end();
    }else if(path=='/pay'){
    //读取 db中用户余额
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1; //余额减1

    fs.writeFileSync('./db',newAmount); //更新余额
    //设置响应头
    response.setHeader('Content-Type','application/javascript');
    //设置状态码
    response.statusCode = 200;
    //返回响应内容
    response.write(
    `
    ${query.callback}.call(undefined,'success')
    `
    );

    response.end();
    }else{
    response.statusCode = 404;
    response.end();
    }

    /******** 代码结束,下面不要看 ************/
    })

    server.listen(port)
    console.log('监听 ' + port + ' 成功\n请在浏览器输入 http://localhost:' + port)

    写了那么多 其实你可以使用jQuery 几句话就能搞定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <h5>您的账户余额是 <span id="amount">&&&amount&&&</span></h5>
    <button id="btn">打钱</button>
    <script src="//code.jquery.com/jquery-1.9.1.min.js"></script>
    <script>
    btn.addEventListener('click',function(){
    $.ajax({
    url:"http://localhost:9999/pay",
    dataType:"jsonp",
    success:function(res){
    console.log(res);
    }
    })
    })
    </script>

    注意: $.ajax()只是把jsonp归纳到 jq里 而它不是ajax

    考点1 :请问JSONP为什么不支持POST请求

    • 因为JSONP是通过动态创建script实现的
    • 我们动态创建script的时候只能用get 没有办法用post

    考点2 : 什么是 JSONP?

    • 1请求方创建一个script标签src指向响应方,并传递callback =回调函数名
    • 2响应方根据callback查询参数构造一个 xxx.call(undefined,传递的内容)
    • 3浏览器接到响应,就会执行 xxx.call(undefined,传递的内容)
    • 4请求方得到他想要的数据