循环发送请求之Javascript递归实现

项目实战问题总结:循环发送请求

循环发送请求,除非必要,否则最好还是不要这么干,尤其是前后端分离项目,应当尽量避免发送多条请求,其实大部分场景下都可以找到可替代的方案。
但不排除一定要这么干的时候,这个需求,可以使用Promise,利用递归思想实现链式发送、处理请求。

我的需求

一个可以多选删除的列表,如果被删除项被一些Service调用,要提示无法删除。

正常思路应该是:把待删除项的id放进数组发给后端,后端返回判断结果,然后前端根据判断结果提示用户。
因为某些原因,实际思路为:前端遍历待删除项的id,依次发送能否删除的请求,如果有一条不能删除,那么所有项都不可删除,根据后端响应提示用户。
所以就用到了野路子——递归实现循环发送请求

代码

private checkReference = (//递归方法在此
        deleteIdList: string[],
        previousItemReference?: boolean,//上一层递归的数据。
    ): Promise<any> => {
     
        const deleteId = deleteIdList.pop()!;
        return deleteId
            ? getExecutionScheduleReference(deleteId)
                .then((data) => {
     
                    const hasReference = data.length > 0 || previousItemReference;
                    return this.checkReference(deleteIdList, hasReference);//在此递归
                })
            : Promise.resolve(previousItemReference);//下文详细介绍Promise.resolve()
    }
private deleteExecutionSchedule = (): Promise<any> => {
     
        const deleteItemId: string[] = this.props.selectionDetails!.map((item) => item.id);
        //待删除ID的Array
        const deleteCopy = [...deleteItemId];
        //复制一下,因为在this.checkReference()执行完之后,deleteItemId就成空数组了。
        // reference check at here. --start
        return this.checkReference(deleteItemId, false)
        	.then((hasReference) => {
     
            	if (hasReference) {
     
                	//不能删除,提示用户
            	} else {
     
                	deleteExecutionSchedule(deleteCopy)
                    	.then(() => {
     
                        	//删除成功回调
                    	})
                    	.catch(() => {
     
                        	//删除失败回调
                    	});
            	}
        });
        // reference check at here. --end
    }

细节

递归实现的重点,就在于利用Promise的链式调用思路,Promise的构造函数接收参数:一个executor,该executor接收两个函数做参数:resolve,reject,便于理解可以直接简单认为resolve是成功回调,reject是失败回调(其实这两个函数意味着将Promise从pendding状态改变为fulfilled或rejected状态)。

const promise = new Promise((resolve,reject)=>{
     
	//异步操作
})

Promise.then(),可以理解为触发Promise,使之执行executor,then()接受两个函数:onFulfilled和onRejected。这两个函数是执行executor,状态变成fulfilled或rejected后调用的函数,实例化Promise时executor中的只是参数,而then()方法中是定义好的函数,then()提供的resolve函数会在executor中被调用。

如果 then 中的回调函数:

  • 返回了一个值,那么 then 返回的 Promise 将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
  • 没有返回任何值,那么 then 返回的 Promise 将会成为接受状态,并且该接受状态的回调函数的参数值为 undefined。
  • 抛出一个错误,那么 then 返回的 Promise 将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
  • 返回一个已经是接受状态的 Promise,那么 then 返回的 Promise 也会成为接受状态,并且将那个 Promise 的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。
  • 返回一个已经是拒绝状态的 Promise,那么 then 返回的 Promise 也会成为拒绝状态,并且将那个 Promise 的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
  • 返回一个未定状态(pending)的 Promise,那么 then 返回 Promise 的状态也是未定的,并且它的终态与那个 Promise 的终态相同;同时,它变为终态时调用的回调函数参数与那个 Promise 变为终态时的回调函数的参数是相同的。
    引用自——MDN-Promise介绍
promise.then((data)=>{
     
	//操作data
})

而Promise.resolve(data)可以直接跳过执行,返回一个状态为fulfilled的Promise,data就是resolve回调函数的参数。(简单理解为此时可以用then((data)=>{ })得到data)。
如代码所示,递归的使用,使得下一个请求总是在当前请求的then()方法中,如此递归下去,直到达到临界条件——待删除id的个数为0,递归结束,此时就构造了一条Promise调用链。
形如:

new Promise(()=>{
     
	//异步操作
}).then(()=>{
     
	new Promise(()=>{
     
		//异步操作
	}).then(()=>{
     
		new Promise(()=>{
     
		//异步操作
		}).then(()=>{
     
			//递归至达到临界条件
		})
	})
})

你可能感兴趣的:(前端实例,前端,递归,循环请求)