前言
最近在学习react,所以本次例子用react书写,写的不好请见谅。
先说需求
绘制一个海报页面,有文字图片等内容,有个二维码图片url需要通过接口获取
再上代码
function App() {
const getQRcodeUrl = () =>
new Promise(resolve => {
setTimeout(() => {
resolve(
'https://img2.baidu.com/it/u=3202947311,1179654885&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500'
)
}, 1000)
})
useEffect(() => {
;(async () => {
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
// 第一步 写文字
ctx.fillText('hello', 0, 20)
// .... 很多步骤
// 绘制背景
const QRcodeUrl = await getQRcodeUrl()
const img = new Image()
img.crossOrigin = 'anonymous'
img.onload = () => {
ctx.drawImage(img, 0, 50, 50, 50)
}
img.src = QRcodeUrl
// .... 很多步骤
})()
}, [])
return <canvas id="canvas" width="100" height="100" />
}
以下是页面展示效果
请求前置
如果getQRcodeUrl接口很慢,那么后续的绘制步骤统统会delay。现在我们把获取url的接口改为页面初始化"created"时候就执行
function App() {
const getQRcodeUrl = useCallback(
() =>
new Promise(resolve => {
setTimeout(() => {
resolve(
'https://img2.baidu.com/it/u=3202947311,1179654885&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500'
)
}, 1000)
}),
[]
)
const getQRcodeUrlPromise = useRef()
useEffect(() => {
getQRcodeUrlPromise.current = getQRcodeUrl()
}, [getQRcodeUrl])
useEffect(() => {
;(async () => {
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
// 第一步 写文字
ctx.fillText('hello', 0, 20)
// .... 很多步骤
// 绘制背景
const QRcodeUrl = await getQRcodeUrlPromise.current
const img = new Image()
img.crossOrigin = 'anonymous'
img.onload = () => {
ctx.drawImage(img, 0, 50, 50, 50)
}
img.src = QRcodeUrl
// .... 很多步骤
})()
}, [])
return <canvas id="canvas" width="100" height="100" />
}
好处
- 不用我说,肯定是快
- 如果"mounted"函数会多次执行,那么
await getQRcodeUrlPromise.current
只会走一次接口请求,且只有第一次可能等待时间会随着接口时间变长,后续在走进来,同Promise.resolve
一样的快
弊端
- 只能适用于请求一次,不会变更后续数据的需求
- 代码量增加不少