实现两个耗时不同的请求更改同一处,并分别执行多次,将最后一次作为最终结果
一、模拟两个耗时不同的请求
const reqa = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('A')
}, 1000)
})
}
const reqb = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('B')
}, 3000)
})
}
二、两个button都可以更改div里面的内容
<body>
<button onClick="clickA()">A</button>
<button onClick="clickB()">B</button>
<div id="message"></div>
</body>
<script>
function clickA() {
document.getElementById('message').innerHTML = 'A'
}
function clickB() {
document.getElementById('message').innerHTML = 'B'
}
</script>
三、通过模拟请求更改div里面的内容
<body>
<div>方法一 给每个请求添加标记</div>
<button onClick="clickA()">A</button>
<button onClick="clickB()">B</button>
<div id="message"></div>
</body>
<script>
const reqa = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('A')
}, 1000)
})
}
const reqb = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('B')
}, 3000)
})
}
function clickA() {
reqa().then(res => {
document.getElementById('message').innerHTML = res
})
}
function clickB() {
reqb().then(res => {
document.getElementById('message').innerHTML = res
})
}
</script>
// 存在一个问题 连续点击A->B->A
// 因为请求耗费时间不同 会显示 A->A->B
// 如何让内容成功显示A就是本文的重点
四、方法一 给每个请求添加标记
var current = 0
function clickA() {
const idx = ++ current
reqa().then(res => {
if(idx == current) {
document.getElementById('message').innerHTML = res
}
})
}
function clickB() {
const idx = ++ current
reqb().then(res => {
if(idx == current) {
document.getElementById('message').innerHTML = res
}
})
}
// 连续点击A->B->A 会显示A
五、方法二 多个请求顺序串联
var currentPromise = Promise.resolve('i')
function clickA() {
currentPromise = currentPromise.then(() => reqa()).then(value => {
document.getElementById('message').innerHTML = value
})
}
function clickB() {
currentPromise = currentPromise.then(() => reqb()).then(value => {
document.getElementById('message').innerHTML = value
})
}
// // 连续点击A->B->A 会显示A->B->A
六、方法三 取消上次请求的回调
var lastCancel = undefined
function cancelAble(req, callback) {
let cb = callback
req().then((value) => {
cb && cb(value)
})
const cancel = () => {
cb = undefined
}
return cancel
}
function clickA() {
this.lastCancel && this.lastCancel()
this.lastCancel = cancelAble(reqa, (value) => {
document.getElementById('message').innerHTML = value
})
}
function clickB() {
this.lastCancel && this.lastCancel()
this.lastCancel = cancelAble(reqb, (value) => {
document.getElementById('message').innerHTML = value
})
}
// 连续点击A->B->A 会显示A
七、完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>方法一 给每个请求添加标记</div>
<button onClick="clickA()">A</button>
<button onClick="clickB()">B</button>
<div id="message"></div>
<div>方法二 多个请求顺序串联</div>
<button onClick="clickA1()">A1</button>
<button onClick="clickB1()">B1</button>
<div id="message1"></div>
<div>方法三 取消上次请求的回调</div>
<button onClick="clickA2()">A2</button>
<button onClick="clickB2()">B2</button>
<div id="message2"></div>
</body>
<script>
// 模拟请求
const reqa = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('A')
}, 1000)
})
}
const reqb = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('B')
}, 3000)
})
}
// 方法一
var current = 0
function clickA() {
const idx = ++ current
reqa().then(res => {
if(idx == current) {
document.getElementById('message').innerHTML = res
}
})
}
function clickB() {
const idx = ++ current
reqb().then(res => {
if(idx == current) {
document.getElementById('message').innerHTML = res
}
})
}
// 方法二
var currentPromise = Promise.resolve('i')
function clickA1() {
currentPromise = currentPromise.then(() => reqa()).then(value => {
document.getElementById('message1').innerHTML = value
})
}
function clickB1() {
currentPromise = currentPromise.then(() => reqb()).then(value => {
document.getElementById('message1').innerHTML = value
})
}
// 方法三
var lastCancel = undefined
function cancelAble(req, callback) {
let cb = callback
req().then((value) => {
cb && cb(value)
})
const cancel = () => {
cb = undefined
}
return cancel
}
function clickA2() {
this.lastCancel && this.lastCancel()
this.lastCancel = cancelAble(reqa, (value) => {
document.getElementById('message2').innerHTML = value
})
}
function clickB2() {
this.lastCancel && this.lastCancel()
this.lastCancel = cancelAble(reqb, (value) => {
document.getElementById('message2').innerHTML = value
})
}
</script>
</html>