数据库加减法之JSONP

这是一篇关于前后台配合,以及JSONP的博客,博客的内容记录了一些关键、比较易错或者较爱遗漏的点。需要你了解前后端交互,并且知道一下JSONP的知识。

some知识点

  1. MySQL 是一种数据库
  2. 文件系统是一种数据库

只要能长久地存数据,就是数据库

1.form表单刷新当前页面

缺点:form刷新默认刷新页面,可以用iframe解决。

2.img请求

①.模拟用户网络不好,请求失败

Math.random()

②.点击后动态创建img,浏览器有个特性。当它发现你在内存中创建了一个img图片,它就去请求图片的src

1
2
3
4
5
6
7
8
9
10
let images = document.createElement('img')
images.src="/pay"

images.onload = ()=>{
alert('打钱成功!')
}

images.onerror = ()=>{
alert('打钱失败!')
}

③.如果提升用户体验,在前端进行提示,需要返回一张图片,来表示iamges.onload,服务端代码如下

1
2
3
4
5
6
7
8
9
else if(path ==='/pay'){
var amount = fs.readFileSync('./db', 'utf8')
var newamount = amount - 1
fs.writeFileSync('./db',newamount)
response.statusCode = 200
response.setHeader('Content-Type', 'images/jpg')
response.write(fs.readFileSync('./1.jpg'))
response.end()
}

img总结:

不刷新无法重新请求,所以给img后面带?

3.script请求

①.前端代码如下

一个重要的细节,script必须要放在body里,才能正常发送请求

1
2
3
4
5
6
7
8
9
10
11
clickMe.addEventListener('click', (e)=>{
let script = document.createElement('script')
script.src="/pay"
document.body.appendChild(script) script.onload=(e)=>{
e.currentTarget.remove()
}
script.onerror = (e) => {
alert('fail')
e.currentTarget.remove()
}
})

②.后端代码如下

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
else if(path ==='/pay'){
var amount = fs.readFileSync('./db', 'utf8')
var newamount = amount - 1
fs.writeFileSync('./db',newamount)
response.statusCode = 200
var i = Math.random();
// response.setHeader('Content-Type', 'images/jpg')
// response.write(fs.readFileSync('./1.jpg'))
response.setHeader('Content-Type', 'application/javascript')
//第一版的返回
//response.write('alert("sucess")')

//第二版的返回
//response.write(`
//alert("success")
//window.location.reload()
// `)

//德芙丝般顺滑版
response.write(`
amount.innerText = amount.innerText -1
`)

response.end()
}

SRJ特点

服务端返回js

key1

script里,可以访问别的域名。

get请求,容易伪造。

1
<script src="http://alipay.com/pay?number=10000&user=www" ></script>

4. JSONP

两个网站间交流

①伪造两个站点交流,修改hosts文件

  • 127.0.0.1 frank.com
  • 127.0.0.1 jack.com

②开两个服务

  • PORT=8001 node server.js
  • PORT=8002 node server.js

这个变更是为了实现代码分离,后端(服务器)只需要调用函数

③-1前端部分代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script>
window.xxx = function(s){
alert(s)
}
clickMe.addEventListener('click', (e)=>{
let script = document.createElement('script')
script.src="http://srdev.izuche.com:8002/pay"
document.body.appendChild(script)
// 前端只需要监控失败
script.onload=(e)=>{
e.currentTarget.remove()
}
script.onerror = (e) => {
alert('fail')
e.currentTarget.remove()
}
})
</script>

③-2后端部分代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
else if(path ==='/pay'){
var amount = fs.readFileSync('./db', 'utf8')
var newamount = amount - 1
fs.writeFileSync('./db',newamount)
response.statusCode = 200
var i = Math.random();
// response.setHeader('Content-Type', 'images/jpg')
// response.write(fs.readFileSync('./1.jpg'))
response.setHeader('Content-Type', 'application/javascript')
response.write(`
//说明 jack.com的后端需要对frank.com的页面细节了解很清楚
//耦合 解耦
// amount.innerText = amount.innerText -1
xxx.call(undefined,'success')
`)
response.end()
}

最终章①:一些优化后,前端代码如下

  1. script加载成功或者失败后,清除callback函数
  2. callback函数名字随机数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <script>
    clickMe.addEventListener('click', (e)=>{
    let script = document.createElement('script')
    let functionName = 'frank'+ parseInt(Math.random()*100000, 10) // 生成随机数
    window[functionName] = function(result){
    if(result === 'success'){
    amount.innerText = amount.innerText -1
    }else{

    }
    }
    script.src="http://srdev.izuche.com:8002/pay?callback="+functionName
    document.body.appendChild(script) script.onload=(e)=>{
    e.currentTarget.remove()
    delete window[functionName] //删除函数
    }
    script.onerror = (e) => {
    alert('fail')
    e.currentTarget.remove()
    delete window[functionName]
    }
    })
    </script>

最终章②:一些优化后,后端代码如下

else if(path ===’/pay’){
var amount = fs.readFileSync(‘./db’, ‘utf8’) //读取数据库
var newamount = amount - 1
fs.writeFileSync(‘./db’,newamount)//写入数据库
response.statusCode = 200
response.setHeader(‘Content-Type’, ‘application/javascript’)
response.write(//说明 jack.com的后端需要对frank.com的页面细节了解很清楚 //耦合 解耦 // amount.innerText = amount.innerText -1 ${query.callback}.call(undefined,'success') //取callback函数名)
response.end()
}

End