JSONP

数据库

有时候,我们需要长久的存储数据,不随着外界因素的改变而改变,这样的数据栖息地可以称之为数据库。

version1.0-表面工作

建立一个扣款功能做例子

JSONP

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>pay</title>
</head>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<body>
    <p>您的账户余额: <span id="amount">100</span></p>
    <button id='button'>付款1块</button>
</body>
<script>
    $('#button').on('click',() => {
        let n=document.getElementById('amount').innerText;
        n -= 1;
        document.getElementById('amount').innerText = n;
    })
</script>
</html>

存在的问题

之所以称之为表面,是因为,所有的操作都是表面现象,当页面刷新时,一切都会回到初始状态。而且,别人很容易就能够获取你的信息。最好是,我们去调取数据库里你的信息,然后显示在页面上。

version2.0-将操作在后端进行

以往,我们是在前端的代码中去改用户的余额。现在,不,我们去后端直接改数据库里的余额,然后,把后端数据库的金额显示在前端页面上。而前端用来向后端发起一个请求,请求更改数据库里的余额。

<button>显然不能发起一个请求,所以使用<form>,表单是可以发起一个请求的,而且可以指定请求的方式:get/post

前端代码:

  • 使用<form>发起一个请求
  • 请求路径action='/pay'
  • 请求方法method='post'
<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>pay</title>
</head>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<body>
    <p>您的账户余额: <span id="amount">$$amount$$</span></p>
    <form id='button' action='/pay' method='post'>
        <input type='submit' value='付款1块钱'>
    </form>
</body>
</html>

使用Javascript写的后端代码:

  • 修改数据库金额,返回成功提示response.write('success');
  • 读取数据库金额
  • 显示数据库金额在页面上
//读取数据库金额,并显示在页面上
if(path === './'){
    var index_string = fs.readFileSync('./index.html','utf8');
    var amount = fs.readFileSync('./db','utf8');
    index_string.replace('$$amount$$',amount);
    response.setHeader('Content-type','text/html;charset=utf-8');
    response.write(string);
    response.end();
    
//修改数据库中金额,并返回success
}else if(path === '/pay' && method === 'post'){
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1;
    fs.writeFileSync('./db',newAmount);
    response.write('success');
    response.end();
}

效果

点击按钮:

点击付款1块钱,发送如下请求,并且页面中显示success。说明请求成功,数据库中金额修改成功!
JSONP

返回页面:
JSONP

查看数据库:
JSONP

存在问题

有没有发现,我们每一次付款,都需要返回、刷新页面才能看到自己正确的余额。用户体验极差!
并且,<form>表单自带特性:每一次提交,都会刷新页面。
最好是,付款之后,页面只有数字那部分局部刷新

version3.1-iframe

<iframe>的功能就是在页面中单开一个空间作为新的页面,我们可以将<form>关联到这个<iframe>上,每次提交都只刷新<iframe>即可。

<body>
    <p>您的账户余额: <span id="amount">$$amount$$</span></p>
    <form id='button' action='/pay' method='post' target='result'>
        <input type='submit' value='付款1块钱'>
    </form>

    <iframe name='result' src='about:blank' frameborder='0' height=200></iframe>
</body>

JSONP

存在的问题

过时。虽然不需要再按返回了,但是还是需要刷新页面才能看到真正的余额。

version3.2-<img>发送请求

既然,我们不希望页面刷新,那我们就得换一个方式发送请求。铛铛铛铛!这就是<img>!不过<img>只能发送get请求,不过,方法先进,用户体验良好,get也可以接受。

前端代码:

  • 注意!功能是在js里实现的
  • 当点击<button>,创建一个<img>,路径指向后台文件/pay
  • 如果图片加载成功image.onload=function(){},提示成功,并将金额amount.innerText -= 1
  • 如果图片加载失败image.onerror=function(){},提示失败
<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>pay</title>
</head>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<body>
    <p>您的账户余额: <span id="amount">$$amount$$</span></p>
    <button id='button'>付款1块钱</button>>
</body>
<script>
    $('#button').on('click',function(){
        var amount=document.getElementById('amount');
        var image=document.createElement('img');
        image.src='./pay';
        image.onload=function(){
            alert('success');
            amount.innerText -= 1;
        }
        image.onerror=function(){
            alert('fail');
        }
    })
</script>

使用Javascript写的后端代码:

  • 与之前区别在于,这次不需要要用到刷新页面,当然刷新页面功能也没问题
  • 与之前区别在于,这次返回的是一张图片response.write(fs.readFileSync(你的图片路径));
//和之前一样,读取数据库中金额,并显示在页面上,但这里并不一定会用到这些代码,因为我们不需要刷新页面了
if(path === './'){
    var index_string = fs.readFileSync('./index.html','utf8');
    var amount = fs.readFileSync('./db','utf8');
    index_string.replace('$$amount$$',amount);
    response.setHeader('Content-type','text/html;charset=utf-8');
    response.write(string);
    response.end();
}

//修改数据库中金额,成功后返回一张图片
else if(path === '/pay'){
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1;
    fs.writeFileSync('./db',newAmount);
    response.setHeader('Content-type','image/jpg');
    response.write(fs.readFileSync(你的图片路径));
    response.end();
}

JSONP

优点

  • 不用像`<iframe>一样新开辟一块地盘
  • 之前的思路:修改后端数据库 → 获取数据库金额显示在页面上(需要刷新页面获得显示)
    现在的思路:修改后端数据库 → 修改成功后,直接修改页面显示(不刷新);获得数据库金额(刷新)
  • 成功、失败的提示依赖alert(),不像之前需要新的页面
  • 机智的地方在:虽然建立了<img>标签,也成功获取了一张图片,但是图片并没有显示出来,因为,我们只是在js里创建了<img>标签,并没有把它加到页面里,没有append()到哪里去。所以,我们利用了<img>能够发送请求的特点,而没有真正的显示出图片。

问题

哇!这样已经很好了,可以返回一个大小很小的图片呀,或者什么乱起八糟的图片。但是,图片毕竟是图片,返回一张图片会影响响应速度。

version3.3-<script>发送请求

我们发现,<script>居然也能发送请求,那更好了,<script>请求返回的是空字符串,那可比图片小多了。

前端代码:

  • js创建<script>,指定<script>路径为./pay
  • <img>发送请求不一样在于:<script>需要加载到<body>才能生效
  • <script>加载成功:script.onload=function(){}
  • <script>加载失败:script.onerror=function(){}
<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>pay</title>
</head>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<body>
    <p>您的账户余额: <span id="amount">$$amount$$</span></p>
    <button id='button'>付款1块钱</button>>
</body>
<script>
    $('#button').on('click',function(){
        var amount=document.getElementById('amount');
        var image=document.createElement('script');
        script.src='./pay';
        document.body.appendChild(script);
        script.onload=function(){
            alert('success');
        }
        script.onerror=function(){
            alert('fail');
        }
    })
</script>

使用Javascript写的后端代码:

  • 与之前区别在于,这次不需要要用到刷新页面,当然刷新页面功能也没问题
  • 与之前区别在于,这次返回的是空字符串response.write('');
//和<img>发送请求时的没有区别
if(path === './'){
    var index_string = fs.readFileSync('./index.html','utf8');
    var amount = fs.readFileSync('./db','utf8');
    index_string.replace('$$amount$$',amount);
    response.setHeader('Content-type','text/html;charset=utf-8');
    response.write(string);
    response.end();
    
//修改数据库中金额,成功后返回空字符串
}else if(path === '/pay'){
    var amount = fs.readFileSync('./db','utf8');
    var newAmount = amount - 1;
    fs.writeFileSync('./db',newAmount);
    response.setHeader('Content-type','application/javascript');
    response.write('');
    response.end();
}

JSONP

优化-1

在使用<script>发送请求的本例中,我们没有在前端代码中加入,当script.onload=function(){}时,页面中数字减一amount.innerText -= 1;。这是因为,经过测试,

在前端代码中加入:

script.onload=function(){
    //之前的代码
    console.log('我是前端');
}

在后端代码中加入:

else if(path === '/pay'){
    //之前的代码
    response.write('console.log("我是后端")');
    //之后的代码
}

结果发现,首先出现后端的console.log("我是后端"),再出现前端的console.log('我是前端')

之前,我们将amount.innerText -= 1;放在前端代码里是因为,之前使用<img>,返回只能是一张图片;现在我们使用<script>,返回值会被当做Javascript执行。

所以,我们直接在后端代码输入我们想要执行的前端代码就行啦

相关推荐