ある面の非同期問題の解析

5377 ワード

前言
この面接問題論は当時私には書けませんでしたが、promiseの結果をよく知っていると自慢していました.
この面接はまだ終わっていません.前から実習生に入社していたからです.
タイトル
//JS               Scheduler,              。     Scheduler ,           
class Scheduler {
  add(promiseCreator) { ... }
  // ...
}

const timeout = (time) => new Promise(resolve => {
  setTimeout(resolve, time)
})

const scheduler = new Scheduler()
const addTask = (time, order) => {
  scheduler.add(() => timeout(time))
    .then(() => console.log(order))
}

addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
// output: 2 3 1 4

//    ,1、2        
// 500ms ,2  ,  2,  3  
// 800ms ,3  ,  3,  4  
// 1000ms ,1  ,  1
// 1200ms ,4  ,  4

プロセスの実行
@左が残り時間、右が出力内容
実行キュー(最大2つ)
待ち行列
動作
実行内容
1000@1
実行キューが満たされていない場合は、直接実行キューに入ります.
addTask(1000, '1')
1000@1、500@2
実行キューが満たされていない場合は、直接実行キューに入ります.
addTask(500, '2')
1000@1、500@2
300@3
実行キューがいっぱいで、待機キューに追加されました
addTask(300, '3')
1000@1、500@2
300@3、400@4
実行キューがいっぱいで、待機キューに追加されました
addTask(400, '4')
500@1、300@3
400@4
500@2完了出力2を実行し、1000@1500を消費し、待機キューから実行キューに順番に追加
200@1、400@4
300@3完了出力3を実行し、500@1300を消費し、待機キューから実行キューに順番に追加
200@4
200@1実行完了出力1
200@4実行完了出力4
構想
注意addメソッドには関数が入ってきてPromiseに戻るのが難点で、多くの人が問題を修正しています.getter、setterで書いたのを見たことがありますが、問題の主旨とは違うと思います.
最初の2つはうまく処理して、実行列の中で満員かどうかを直接判断して、満員ではありませんて直接チームに入ります
3つ目以降は前両者がresolveであるか否かを判断する必要があり、ここで、前の2つと前の2つの概念が異なることに注意してください(抽象的であるため、ここでは例を挙げて説明します:現在3つ目で、前の2つの前者は1つ目から1つ目を指し、後者は2つ目を指します;現在4つ目で、前の2つの前者は1つ目から2つ目を指し、後者は3つ目を指します;このように押します).resolve後、待機キューから実行キューに順番に追加されます.
原因を言うと、二つの状況があります.前者が先に完了し、すなわち集合中のタスクがすべて完了すると、後者は必ず実行(未完了)に入り、実行キューには必ず1つの位置が残ります.後者が先に完成し、これは何も言うことはありません.後者が完成したら必ず1つの位置が残ります.
コード#コード#
class Scheduler {
    constructor() {
        this.list=[]   //promise list
        this.cur=0   //current position
        this.max=2
    }
    add(promiseCreator) {
        let temp=null;

        if(this.cur < this.max) {
            temp=promiseCreator();
        }else {
            let arr=this.list.slice(0,this.cur-1);
            let all=Promise.all(arr);
            
            temp=Promise.race([all,this.list[this.cur-1]])
                    .then(() => {
                        return promiseCreator();
                    });
        }

        this.list.push(temp);
        this.cur++;
        return temp;
    }
}

欠点と不足
  • 多重化できない実行キューの最大個数が3以上に調整すると、前n者のうちresolve
  • があるか否かを判断する必要がある.
  • 容易メモリ爆発listはprimiseをずっと保存しており、resolveでもpeddingでも
  • 異常処理
  • コメントエリアの質問
    基本的にすべてのコメントエリアの考え方は悪くありません.それからほとんどの人は元promiseのデータを投げ出すことを考えていません(先輩が発見しました)、実際に応用すれば、必ずデータを適切にしなければなりません.原題は言及していませんが.
    最後に
    仲間がいて他の考えがあったり、欠点について考えがあったりしたらコメントを歓迎します.
    転載先:https://juejin.im/post/5d37e392f265da1ba252a226