V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
chashao
V2EX  ›  问与答

一道 promise 的题目,求大佬解答

  •  
  •   chashao · 2019-07-17 22:32:01 +08:00 · 1642 次点击
    这是一个创建于 1958 天前的主题,其中的信息可能已经有所发展或是发生改变。
    class Scheduler {
        add(promiseCreator) {
              // 需要实现
        }
    }
    
    const timeout = (time) => new Promise(resolve => {
        console.log('in timeout:', time);
        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
    
       
    
    
    
    
    
    
    
    11 条回复    2019-07-19 23:19:22 +08:00
    chashao
        1
    chashao  
    OP
       2019-07-17 22:32:43 +08:00
    这道题的要求是并行执行,并行最多两个任务。
    meszyouh
        2
    meszyouh  
       2019-07-18 08:38:57 +08:00 via Android
    看起来还于 timeout 有关?总是接在时间最少的部分?
    kamilic
        3
    kamilic  
       2019-07-18 10:01:28 +08:00   ❤️ 1
    ```javascript
    class Scheduler {
    constructor() {
    this.__maxQueueSize = 2;
    this.__runningJobs = [];
    this.__pendingQueue = [];
    }

    get isJobsFull() {
    return this.__maxQueueSize <= this.__runningJobs.length;
    }

    static jobWrapper(promiseCreator) {
    Scheduler.__jobId += 1;
    const id = Scheduler.__jobId;
    const wrappedPromise = promiseCreator().then((result) => {
    return {
    id,
    result
    };
    });
    wrappedPromise.__jobId = id;
    return wrappedPromise;
    }

    removeFinishedJob(id) {
    console.log(`remove ${id}`);
    this.__runningJobs = this.__runningJobs.reduce((curr, job) => {
    if (job.__jobId !== id) {
    curr.push(job);
    }
    return curr;
    }, []);
    console.log(this.__runningJobs);
    }

    async add(promiseCreator) {
    if (!this.isJobsFull) {
    const job = Scheduler.jobWrapper(promiseCreator);
    this.__runningJobs.push(job);
    const {result, id} = await job;
    this.removeFinishedJob(id);
    return result;
    } else {
    this.__pendingQueue.unshift(promiseCreator);
    await Promise.race(this.__runningJobs);
    if (this.__pendingQueue.length > 0) {
    return this.add(this.__pendingQueue.pop());
    }
    }
    }
    }

    Scheduler.__jobId = 0;
    ```

    昨晚一时兴起写了一下,希望对你有帮助。。
    kamilic
        4
    kamilic  
       2019-07-18 10:02:21 +08:00
    ??不支持 md 的?
    zbinlin
        5
    zbinlin  
       2019-07-18 10:09:27 +08:00
    这是面试题吗?如果是的话,我肯定会挂的 :(

    paste.ubuntu.com/p/Rm6dDmWxkN/
    zbinlin
        6
    zbinlin  
       2019-07-18 10:10:45 +08:00   ❤️ 1
    chashao
        7
    chashao  
    OP
       2019-07-18 10:45:52 +08:00
    @meszyouh 是的,timeout 最小的任务最先完成,之后的任务就能添加进来。
    chashao
        8
    chashao  
    OP
       2019-07-18 10:46:20 +08:00
    @zbinlin 是字节跳动的校招题
    WhoAmIAndwhoAreU
        9
    WhoAmIAndwhoAreU  
       2019-07-18 10:51:43 +08:00
    插眼
    meszyouh
        10
    meszyouh  
       2019-07-18 13:18:06 +08:00   ❤️ 1
    autoxbc
        11
    autoxbc  
       2019-07-19 23:19:22 +08:00
    收到 #6 @zbinlin 答案的启发,写了个简化版,应该更好理解一点

    https://gist.github.com/autoxbc/410c381aca4772736dfe22f6b4590c46
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1070 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:12 · PVG 03:12 · LAX 11:12 · JFK 14:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.