一道前端面試題引起的學習

題目:

請實現以下函數,能夠批量請求數據,全部的 url 地址在 urls 參數中,同時能夠經過 max 參數控制請求的併發數,當全部請求結束以後,須要執行 callback 回調函數,發送請求的函數能夠直接使用 fetch 便可javascript

小白陷阱

題中有一個關鍵詞「併發」,對於我這種前端小白第一次解答這道題目就掉入陷阱了, 解成了並行,😅前端

概念解析

說到併發咱們能夠先來理解‘串行’,‘並行’,‘併發’這三個概念
複製代碼
  • 串行 當前任務執行完以後,才能執行下一個任務
  • 並行 多任務同時進行,互不影響
  • 併發 多任務在同一時間間隔發生

舉個例子來幫助咱們更好的理解:好比一我的洗衣服跟燒菜java

  • 串行就是: 你只能先作其中的某一件事,作完以後才能去作下一件事情
  • 並行就是: 你右手燒菜,左手洗衣服同時進行
  • 併發就是: 你一下子燒菜,一下子又去洗衣服

到這裏相信你們對上述的三個概念有了一點了解,接下里咱們就來實現上面這道面試題:面試

試題實現

<script type="text/javascript">
		let bodyElement = document.body
	    let urls = [
	      'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2580986389,1527418707&fm=27&gp=0.jpg',
	      'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1995874357,4132437942&fm=27&gp=0.jpg',
	      'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2640393967,721831803&fm=27&gp=0.jpg',
	      'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1548525155,1032715394&fm=27&gp=0.jpg',
	      'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2434600655,2612296260&fm=27&gp=0.jpg',
	      'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2160840192,133594931&fm=27&gp=0.jpg'
	    ]
	    let max = 2
	    let callback = () => {
	      console.log('全部請求完成了')
	    }

	    class Concurrent {
	    	constructor(urls, max, callback) {
	    		this.urls = urls
	    		this.max = max
	    		this.callback = callback
	    	  	this.currentIndex = 0
	    	}

	    	addQueue() {
	    		for(let i = 0, len = this.urls.length; i < len; i++) {
	    			if (this.currentIndex < this.max) {
    					this.request()
    					break
	    			}
    				
    				this.currentIndex++
	    		}
	    	}

	    	request() {
	    		let tiemout = Math.random() * 1000
	    		
	    		fetch(this.urls[this.currentIndex])
	    		.then(res => res.blob())
	    		.then(res => {
	    			let src = URL.createObjectURL(res)
	    			bodyElement.innerHTML += `<img src=${src} />`
	    		})
	    		.catch(fail => {
	    			
	    		})
	    		.finally(() => {
	    			if (++this.currentIndex < this.urls.length) {
	    			    // 用延時器是由於反應接口太快 以便於觀察
	    				return setTimeout(() => {
		    				this.request()
		    			}, tiemout)
		    		}

		    		this.callback()
	    		})
	    	}
	    }

	    function sendRequest(urls, max, callback) {
			let concurrent = new Concurrent(urls, max, callback)
			concurrent.addQueue()
	    }

	    sendRequest(urls, max, callback)
	</script>
複製代碼

謝謝你們的閱讀,有錯誤之處,敬請指教。bash

相關文章
相關標籤/搜索