とても啓発的な面接問題です.

12057 ワード

テーマの要求は以下の通りです.
LazyMan('Tony');
// Hi I am Tony

LazyMan('Tony').sleep(10).eat('lunch');
// Hi I am Tony
//    10 ...
// I am eating lunch

LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// Hi I am Tony
// I am eating lunch
//    10 ...
// I am eating diner

LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
//    5 ...
// I am eating lunch
// I am eating dinner
//    10 ...
// I am eating junk food
sleepを見て、後から他の操作をするのはpromiseを使う反応ですか?間違いなく最初は私もそう思いました.しかし、タイトルはチェーン式の呼び出し(jqueryのように、$app..addClass(‘main’).remove()に関連しています.)で、現在のインスタンスに戻るべきですので、promiseを使うのはテーマに合わないです.
テーマ分析:
  • タイトルはチェーン式呼び出しを満たす必要があります.
  • sleep First実行優先度最高
  • 実行はシリアルで、Aを実行してから、B
  • を実行できます.
    一種類の書き方
    class LazyMan{
    
    	constructor(name){
    		console.log(`Hi I am ${name}`)
    		this.taskList = []
    		setTimeout(this.next.bind(this), 0)
    	}
    
    	next(){
    		const fn = this.taskList.shift()
    		fn && fn()
    	}
    
    	sleep(time){
    		const fn = ()=>{
    			setTimeout(()=>{
    				console.log(`   ${time} `)
    				this.next()
    			}, time * 1000)
    		}
    		this.taskList.push(fn)
    		return this
    	}
    
    	sleepFirst(time){
    		const fn = ()=>{
    			setTimeout(()=>{
    				console.log(`   ${time} `)
    				this.next()
    			}, time * 1000)
    		}
    		this.taskList.unshift(fn)
    		return this
    	}
    
    	eat(some){
    		const fn = ()=>{
    			console.log(`I am eating ${some}`)
    			this.next()
    		}
    		this.taskList.push(fn)
    		return this
    	}
    	
    }
    
    書き方の分析
  • は、配列を使用してスタック
  • を実現する.
  • は、関数を実行するたびに、次の関数を呼び出します.これはAを実行してこそ、Bを実行することができます.
  • Q&A
    1.ポーリングを使用して配列スタックを実行してもいいですか?実行可能ですが、前の関数の実行が完了することを保証します.考え方:グローバル変数を使用して、現在の関数の実行が完了したかどうかを表します.