<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      js需要同時發(fā)起百條接口請求怎么辦?--通過Promise實現(xiàn)分批處理接口請求

      如何通過 Promise 實現(xiàn)百條接口請求?
      實際項目中遇到需要發(fā)起上百條Promise接口請求怎么辦?

      前言

      • 不知你項目中有沒有遇到過這樣的情況,反正我的實際工作項目中真的遇到了這種玩意,一個接口獲取一份列表,列表中的每一項都有一個屬性需要通過另一個請求來逐一賦值,然后就有了這份封裝
      • 真的是很多功能都是被逼出來的
      • 這份功能中要提醒一下:批量請求最關(guān)鍵的除了分批功能之外,適當(dāng)?shù)萌∠蝿?wù)和繼續(xù)任務(wù)也很重要,比如用戶到了這個頁面后,正在發(fā)起百條數(shù)據(jù)請求,但是這些批量請求還沒完全執(zhí)行完,用戶離開了這個頁面,此時就需要取消剩下正在發(fā)起的請求了,而且如果你像我的遇到的項目一樣,頁面還會被緩存,那么為了避免用戶回到這個頁面,所有請求又重新發(fā)起一遍的話,就需要實現(xiàn)繼續(xù)任務(wù)的功能,其實這個繼續(xù)任務(wù)比斷點續(xù)傳簡單多了,就是過濾到那些已經(jīng)賦值的數(shù)據(jù)項就行了
      • 如果看我啰啰嗦嗦一堆爛東西沒看明白的話,就直接看下面的源碼吧

      源碼在此!

      • 【注】:這里的 httpRequest 請根據(jù)自己項目而定,比如我的項目是uniapp,里面的http請求是 uni.request,若你的項目是 axios 或者 ajax,那就根據(jù)它們來對 BatchHttp 中的某些部分進(jìn)行相應(yīng)的修改

      • 比如:其中的 cancelAll() 函數(shù),若你的 http 取消請求的方式不同,那么這里取消請求的功能就需要相應(yīng)的修改,若你使用的是 fetch 請求,那除了修改 cancelAll 功能之外,singleRequest 中收集請求任務(wù)的方式也要修改,因為 fetch 是不可取消的,需要借助 AbortController 來實現(xiàn)取消請求的功能,

      • 提示一下,不管你用的是什么請求框架,你都可以自己二次封裝一個 request.js,功能就仿照 axios 這種,返回的對象中包含一個 abort() 函數(shù)即可,那么這份 BatchHttp 也就能適用啦

      • 簡單案例測試 -- batch-promise-test.html

          <!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>
        
          </body>
          <script>
        
            /**
             * 批量請求封裝
             */
            class BatchHttp {
        
          	/** 
          	 * 構(gòu)造函數(shù) 
          	 * */
          	constructor() {
          	}
        
          	/** 
          	 * 單個數(shù)據(jù)項請求 
          	 * @private
          	 * @param {Object} reqOptions - 請求配置
          	 * @param {Object} item - 數(shù)據(jù)項 
          	 * @returns {Promise} 請求Promise
          	*/
          	#singleRequest(item) {
          	  return new Promise((resolve, _reject) => {
          		// 模擬異步請求
          		console.log(`發(fā)起模擬異步請求 padding...: 【${item}】`)
          		setTimeout(() => {
          		  console.log(`模擬異步請求 success -- 【 ${item}】`)
          		  resolve()
          		}, 200 + Math.random() * 800)
          	  })
          	}
        
          	#chunk(array, size) {
          	  const chunks = []
          	  let index = 0
        
          	  while (index < array.length) {
          		chunks.push(array.slice(index, size + index))
          		index += size
          	  }
        
          	  return chunks
          	}
        
          	/**
          	 * 批量請求控制
          	 * @private
          	 * @async
          	 * @returns {Promise}
          	*/
          	async #batchRequest() {
          	  const promiseArray = []
          	  let data = [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, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
        
          	  data.forEach((item, index) => {
          		// 原來的錯誤邏輯(原來的邏輯,導(dǎo)致所有的 Promise 回調(diào)函數(shù)都會被直接執(zhí)行,那么就只有對 response 進(jìn)行分批的功能了)
          		// const requestPromise = this.#singleRequest(item)
          		// promiseArray.push(requestPromise)
        
          		// -- 修改為:
          		promiseArray.push(index)
          	  })
        
          	  const promiseChunks = this.#chunk(promiseArray, 10) // 切分成 n 個請求為一組
        
          	  let groupIndex = 1
          	  for (let ckg of promiseChunks) {
          		// -- 修改后新增邏輯(在發(fā)起一組請求時,收集該組對應(yīng)的 Promiise 成員)
          		const ck = ckg.map(idx => this.#singleRequest(data[idx]))
          		// 發(fā)起一組請求
          		const ckRess = await Promise.all(ck) // 控制并發(fā)數(shù)
          		console.log(`------ 第${groupIndex}組分批發(fā)起完畢 --------`)
          		groupIndex += 1
          	  }
          	}
        
          	/**
          	 * 執(zhí)行批量請求操作
          	 */
          	exec(options) {
          	  this.#batchRequest(options)
          	}
            }
        
            const batchHttp = new BatchHttp()
            setTimeout(() => {
          	batchHttp.exec()
            }, 2000)
          </script>
        
          </html>
        
      • BatchHttp.js

          // 注:這里的 httpRequest 請根據(jù)自己項目而定,比如我的項目是uniapp,里面的http請求是 uni.request,若你的項目是 axios 或者 ajax,那就根據(jù)它們來對 BatchHttp 中的某些部分
          import httpRequest from './httpRequest.js'
        
          /**
           * 批量請求封裝
           */
          export class BatchHttp {
        
          	/** 
          	 * 構(gòu)造函數(shù) 
          	 * @param {Object} http - http請求對象(該http請求攔截器里切勿帶有任何有關(guān)ui的功能,比如加載對話框、彈窗提示框之類),用于發(fā)起請求,該http請求對象必須滿足:返回一個包含取消請求函數(shù)的對象,因為在 this.cancelAll() 函數(shù)中會使用到
          	 * @param {string} [passFlagProp=null] - 用于識別是否忽略某些數(shù)據(jù)項的字段名(借此可實現(xiàn)“繼續(xù)上一次完成的批量請求”);如:passFlagProp='url' 時,在執(zhí)行 exec 時,會過濾掉 items['url'] 不為空的數(shù)據(jù),借此可以實現(xiàn)“繼續(xù)上一次完成的批量請求”,避免每次都重復(fù)所有請求
          	 */ 
          	constructor(http=httpRequest, passFlagProp=null) {
          		/** @private @type {Object[]} 請求任務(wù)數(shù)組 */
          		this.resTasks = []
          		/** @private @type {Object} uni.request對象 */
          		this.http = http
          		/** @private @type {boolean} 取消請求標(biāo)志 */
          		this.canceled = false
          		/** @private @type {string|null} 識別跳過數(shù)據(jù)的屬性 */
          		this.passFlagProp = passFlagProp
          	}
        
        
          	/**
          	 * 將數(shù)組拆分成多個 size 長度的小數(shù)組
          	 * 常用于批量處理控制并發(fā)等場景
          	 * @param {Array} array - 需要拆分的數(shù)組
          	 * @param {number} size - 每個小數(shù)組的長度
          	 * @returns {Array} - 拆分后的小數(shù)組組成的二維數(shù)組
          	*/
          	#chunk(array, size) {
          		const chunks = []
          		let index = 0
        
          		while(index < array.length) {
          		chunks.push(array.slice(index, size + index))
          		index += size;
          		}
        
          		return chunks
          	}
        
          	/** 
          	 * 單個數(shù)據(jù)項請求 
          	 * @private
          	 * @param {Object} reqOptions - 請求配置
          	 * @param {Object} item - 數(shù)據(jù)項 
          	 * @returns {Promise} 請求Promise
          	*/
          	#singleRequest(reqOptions, item) {
          		return new Promise((resolve, _reject) => {
          			const task = this.http({
          				url: reqOptions.url, 
          				method: reqOptions.method || 'GET',
          				data: reqOptions.data,
          				success: res => {
          					resolve({sourceItem:item, res})
          				}
          			})
          			this.resTasks.push(task)
          		})
          	}
        
          	/**
          	 * 批量請求控制
          	 * @private
          	 * @async
          	 * @param {Object} options - 函數(shù)參數(shù)項
          	 * @param {Array} options.items - 數(shù)據(jù)項數(shù)組
          	 * @param {Object} options.reqOptions - 請求配置  
          	 * @param {number} [options.concurrentNum=10] - 并發(fā)數(shù)
          	 * @param {Function} [options.chunkCallback] - 分塊回調(diào) 
          	 * @returns {Promise}
          	*/
          	async #batchRequest({items, reqOptions, concurrentNum = 10, chunkCallback=(ress)=>{}}) {
          		const promiseArray = []
          		let data = []
          		const passFlagProp = this.passFlagProp
          		if(!passFlagProp) {
          			data = items
          		} else {
          			// 若設(shè)置獨立 passFlagProp 值,則篩選出對應(yīng)屬性值為空的數(shù)據(jù)(避免每次都重復(fù)請求所有數(shù)據(jù),實現(xiàn)“繼續(xù)未完成的批量請求任務(wù)”)
          			data = items.filter(d => !Object.hasOwnProperty.call(d, passFlagProp) || !d[passFlagProp])
          		}
          		// --
          		if(data.length === 0) return
        
          		data.forEach((item,index) => {
          			// 原來的錯誤邏輯(原來的邏輯,導(dǎo)致所有的 Promise 回調(diào)函數(shù)都會被直接執(zhí)行,那么就只有對 response 進(jìn)行分批的功能了)
          			// const requestPromise = this.#singleRequest(reqOptions, item)
          			// promiseArray.push(requestPromise)
          			// -- 修改為:這里暫時只記錄下想對應(yīng)的 data 的數(shù)組索引,以便分組用,當(dāng)然這部分有關(guān)分組代碼還可以進(jìn)行精簡,比如直接使用 data.map進(jìn)行收集等方式,但是為了與之前錯誤邏輯形成對比,這篇文章里還是這樣寫比較完整
          			promiseArray.push(index)
          		})
        
          		const promiseChunks = this.#chunk(promiseArray, concurrentNum) // 切分成 n 個請求為一組
        
          		for (let ckg of promiseChunks) {
          			// -- 修改后新增邏輯(在發(fā)起一組請求時,收集該組對應(yīng)的 Promiise 成員)
          			const ck = ckg.map(idx => this.#singleRequest(data[idx]))
          			// 若當(dāng)前處于取消請求狀態(tài),則直接跳出
          			if(this.canceled) break
          			// 發(fā)起一組請求
          			const ckRess = await Promise.all(ck) // 控制并發(fā)數(shù)
          			chunkCallback(ckRess) // 每完成組請求,都進(jìn)行回調(diào)
          		}
          	}
        
          	/**
          	 * 設(shè)置用于識別忽略數(shù)據(jù)項的字段名
          	 * (借此參數(shù)可實現(xiàn)“繼續(xù)上一次完成的批量請求”);
          	 * 如:passFlagProp='url' 時,在執(zhí)行 exec 時,會過濾掉 items['url'] 不為空的數(shù)據(jù),借此可以實現(xiàn)“繼續(xù)上一次完成的批量請求”,避免每次都重復(fù)所有請求
          	 * @param {string} val 
          	 */
          	setPassFlagProp(val) {
          		this.passFlagProp = val
          	}
        
          	/**
          	 * 執(zhí)行批量請求操作
          	 * @param {Object} options - 函數(shù)參數(shù)項
          	 * @param {Array} options.items - 數(shù)據(jù)項數(shù)組
          	 * @param {Object} options.reqOptions - 請求配置  
          	 * @param {number} [options.concurrentNum=10] - 并發(fā)數(shù)
          	 * @param {Function} [options.chunkCallback] - 分塊回調(diào) 
          	 */
          	exec(options) {
          		this.canceled = false
          		this.#batchRequest(options)
          	}
        
          	/**
          	 * 取消所有請求任務(wù)
          	 */
          	cancelAll() {
          		this.canceled = true
          		for(const task of this.resTasks) {
          			task.abort()
          		}
          		this.resTasks = []
          	}
          }
        

      調(diào)用案例在此!

      • 由于我的項目是uni-app這種,方便起見,我就直接貼上在 uni-app 的頁面 vue 組件中的使用案例

      • 案例代碼僅展示關(guān)鍵部分,所以比較粗糙,看懂參考即可

          <template>
          	<view v-for="item of list" :key="item.key">
          		<image :src="item.url"></image>
          	</view>
          	</template>
          	<script>
          	import { BatchHttp } from '@/utils/BatchHttp.js'
        
          	export default {
          		data() {
          			return {
          				isLoaded: false,
          				batchHttpInstance: null,
          				list:[]
          			}
          		},
          		onLoad(options) {
          			this.queryList()
          		},
          		onShow() {
          			// 第一次進(jìn)頁面時,onLoad 和 onShow 都會執(zhí)行,onLoad 中 getList 已調(diào)用 batchQueryUrl,這里僅對緩存頁面后再次進(jìn)入該頁面有效
          			if(this.isLoaded) {
          				// 為了實現(xiàn)繼續(xù)請求上一次可能未完成的批量請求,再次進(jìn)入該頁面時,會檢查是否存在未完成的任務(wù),若存在則繼續(xù)發(fā)起批量請求
          				this.batchQueryUrl(this.dataList)
          			}
          			this.isLoaded = true
          		},
          		onHide() {
          			// 頁面隱藏時,會直接取消所有批量請求任務(wù),避免占用???源(下次進(jìn)入該頁面會檢查未完成的批量請求任務(wù)并執(zhí)行繼續(xù)功能)
          			this.cancelBatchQueryUrl()
          		},
          		onUnload() {
          			// 頁面銷毀時,直接取消批量請求任務(wù)
          			this.cancelBatchQueryUrl()
          		},
          		onBackPress() {
          			// 路由返回時,直接取消批量請求任務(wù)(雖然路由返回也會執(zhí)行onHide事件,但是無所胃都寫上,會判斷當(dāng)前有沒有任務(wù)的)
          			this.cancelBatchQueryUrl()
          		},
          		methods: {
          			async queryList() {
          				// 接口不方法直接貼的,這里是模擬的列表接口
          				const res = await mockHttpRequest()
          				this.list = res.data
        
          				// 發(fā)起批量請求
          				// 用 nextTick 也行,只要確保批量任務(wù)在列表dom已掛載完成之后執(zhí)行即可
          				setTimeout(()=>{this.batchQueryUrl(resData)},0)
          			},
          			/**
          			 * 批量處理圖片url的接口請求
          			 * @param {*} data 
          			 */
          			 batchQueryUrl(items) {
          				let batchHttpInstance = this.batchHttpInstance
          				// 判定當(dāng)前是否有正在執(zhí)行的批量請求任務(wù),有則直接全部取消即可
          				if(!!batchHttpInstance) {
          					batchHttpInstance.cancelAll()
          					this.batchHttpInstance = null
          					batchHttpInstance = null
          				}
          				// 實例化對象
          				batchHttpInstance = new BatchHttp()
          				// 設(shè)置過濾數(shù)據(jù)的屬性名(用于實現(xiàn)繼續(xù)任務(wù)功能)
          				batchHttpInstance.setPassFlagProp('url') // 實現(xiàn)回到該緩存頁面是能夠繼續(xù)批量任務(wù)的關(guān)鍵一步 <-----
          				const reqOptions = { url: '/api/product/url' }
          				batchHttpInstance.exec({items, reqOptions, chunkCallback:(ress)=>{
          					let newDataList = this.dataList
          					for(const r of ress) {
          						newDataList = newDataList.map(d => d.feId === r['sourceItem'].feId ? {...d,url:r['res'].msg} : d)
          					}
        
          					this.dataList = newDataList
          				}})
        
          				this.batchHttpInstance = batchHttpInstance
          			},
          			/**
          			 * 取消批量請求
          			 */
          			cancelBatchQueryUrl() {
          				if(!!this.batchHttpInstance) {
          					this.batchHttpInstance.cancelAll()
          					this.batchHttpInstance = null
          				}
          			},
          		}
          	}
          	</script>
        
      posted @ 2024-07-16 20:43  二價亞鐵  閱讀(927)  評論(5)    收藏  舉報
      主站蜘蛛池模板: 少妇人妻真实偷人精品| 国产精品亚洲一区二区三区| 18禁黄网站免费| 久久99久国产精品66| 国产极品美女高潮抽搐免费网站| 日本一区二区三区专线| 国产成人精品日本亚洲网站| 青草热在线观看精品视频| 一区二区三区四区五区黄色 | 日韩精品区一区二区三vr| 精品一二三四区在线观看| 国产精品SM捆绑调教视频| 伊人欧美在线| 日本中文一区二区三区亚洲| 国产精品综合色区在线观| 国产拍拍拍无码视频免费| 国产日韩一区二区在线| 又大又硬又爽免费视频| 国产永久免费高清在线观看| 全部免费毛片在线播放| 无遮挡aaaaa大片免费看| 一本精品99久久精品77| 极品少妇xxxx| 国产精品麻豆成人av网| 亚洲精品综合网二三区| 亚洲丶国产丶欧美一区二区三区| 免费观看全黄做爰大片| 亚洲欧洲一区二区福利片| 91超碰在线精品| AV秘 无码一区二| 白嫩人妻精品一二三四区| 欧美一级高清片久久99| 色欲国产精品一区成人精品| 老色鬼永久精品网站| 99在线视频免费观看| 高清自拍亚洲精品二区| 四虎女优在线视频免费看| 人妻少妇不满足中文字幕| 丁香五月亚洲综合在线国内自拍| 国产精品一起草在线观看| 国产偷窥熟女精品视频大全|