亲宝软件园·资讯

展开

Vue超详细讲解重试机制示例

loyd3 人气:0

重试指的是当加载出错时,有能力重新发起加载组件的请求。

异步组件加载失败后的重试机制,与请求服务端接口失败后的重试机制一样。所以,先来讨论接口请求失败后的重试机制是如何实现的, 为此,需要封装一个fetch函数,用来模拟接口请求:

function fetch(){
	return new Promise((resolve,reject) => {
		// 请求会在1秒后失败
		setTimeout(()=>{
			reject('err')
		},1000)
	})
}

为了实现失败后的重试,需要封装一个load函数,如下面代码所示:

// load函数接收一个onError回调函数
function load(onError){
	// 请求接口,得到Promise实例
	const p = fetch()
	// 捕获错误
	return p.catch(err=>{
		// 当错误发生时,返回一个新的Promise实例,并调用onError回调
		// 同时将retry函数作为onError回调的参数
		return new Promise((resolve,reject)=>{
			// retry函数,用来执行重试的函数,执行该函数会重新调用load函数并发送请求
			const retry = () => resolve(load(onError))
			const fail = () => reject(err)
			onError(retry, fail)
		})
	})
}

load函数内部调用fetch函数来发送请求,并得到一个Promise实例,并把该实例的resolve

和reject方法暴露给用户,让用户来决定下一步应该怎么做。这里,将新的Promise实例的resolve和reject分别封装为retry函数和fail函数,并将它们作为onError回调函数的参数。

这样,用户就可以在错误发生时主动选择重试或直接抛出错误。

下面的代码展示了用户时如何进行重试加载的:

// 调用load函数加载资源
load(
	// onError回调
	(retry) => {
		// 失败后重试
		retry()
	}
).then(res=>{
	// 成功
	console.log(res)
})

基于这个原理,就可以很容易地将其整合到异步组件的加载流程中,具体实现如下:

function defineAsyncComponent(options){
	if(typeof options === 'function'){
		options = {
			loader: options
		}
	}
	const {loader} = options
	let InnerComp = null
	// 记录重试次数
	let retries = 0
	// 封装load函数用来加载异步组件
	function load(){
		return loader()
				.catch((err)=>{
					// 如果用户指定了onError回调,则将控制权交给用户
					if(options.onError){
						return new Promise((resolve,reject) => {
							// 重试
							const retry = () => {
								resolve(load())
								retries++
							}
							// 失败
							const fail = () => reject(err)
							// 作为onError回调函数的参数,让用户来决定下一步怎么做
							options.onError(retry, fail, retries)
						})
					}else{
						throw error
					}
				}
	}
	return {
		name: 'AsyncComponentWrapper',
		setup(){
			const loaded = ref(false)
			const error = shallowRef(null)
			const loading = ref(false)
			let loadingTimer = null
			if(options.delay){
				loadingTimer = setTimeout(()=>{
					loading.value = true
				}, options.delay);
			}else{
				loading.value = true
			}
			// 调用load函数加载组件
			load()
				.then(c=>{
					InnerComp = c
					loaded.value = true
				})
				.catch((err)=>{
					err.value = err
				})
				.finally(()=>{
					loading.value = false
					clearTimeout(loadingTimer)
				})
			// 省略部分代码
		}
	}
}

加载全部内容

相关教程
猜你喜欢
用户评论