#38 可以开车了吗?


  • 0
    administrators

    黄小明是老司机了,他每天任务就是送一群人去上班。但是每天送的人数不一样,这些人上车的时间也不一样。小明总是要等到人齐才能开车。

    完成函数 driveCustomers,它接受不定数量的参数,这是参数都是函数,每个函数代表一个人。这些函数都接受一个回调函数作为参数,当回调函数被调用的时候说明这个人已经上车了,回调函数会被传入人名。例如:

    const MissLi = (callback) => {
      setTimeout(() => {
        callback('MissLi')
      }, 10) // 上车时间不一定
    }
    
    const MrWang = (callback) => {
      setTimeout(() => {
        callback('MrWang')
      }, 3) // 上车时间不一定
    }
    
    // ..
    
    driveCustomers(MissLi, MarWang, ...)
    

    请你完成 driveCustomers 函数,它的作用是:当人都到齐以后,按上车的时间顺序把人名放到一个数组里面然后传给 drive 函数,正式开车。例如:drive(['MrWang', 'MissLi'])

    你只需要完成 driveCustomers 函数,drive 函数已经可以直接使用。


  • 0

    @ScriptOJ 为什么说我人齐不开车啊...

    const driveCustomers = (...fns) => {
      const customers = []
      fns.forEach(fn => fn(p => {
        customers.push(p)
      }))
      const promises = fns.map(fn => new Promise(fn))
      Promise.all(promises).then(() => {
        drive(customers)
      })
    }
    

  • 1

    const driveCustomers = (...fns) => {
    let customers = [];
    const promises = fns.map(fn=>new Promise((resolve)=>{
    fn((p)=>{
    customers.push(p);
    resolve();
    })
    }));
    Promise.all(promises).then(() => {
    drive(customers)
    })
    }


  • 0

    @nikaple promise用法不对


  • 0

    const driveCustomers = (...args) => {
    let all = [];
    let passers =[];
    all = args.reduce((acc,val) => acc.concat(new Promise( (resolve) => {
    val((p)=>{
    passers.push(p);
    resolve();
    });
    })),[]);
    Promise.all(all).then(() =>drive(passers));
    }


  • 1

    const driveCustomers = (...fns) => {
      const customers = []
      
      fns.forEach(fn => {
        fn(name => {
          customers.push(name)
          
          if (customers.length === fns.length) {
            drive(customers)
          }
        })
      })
    }
    

  • 0

    @tlj 厉害,原来不需要promsie的呀,我以为要用all


  • 0

    @fun 使用Promise.all控制并发流程,感谢提供思路


  • 0

    好题目,借鉴了评论区各位大神的思路:

    /**
     * 方法1:
     * 每个异步任务执行结束后,判断一下是否所有任务都结束了
     */
    var driveCustomers = (...fns) => {
      let names = []
      for (const fn of fns) {
        fn((name) => {
          names.push(name) // 执行本任务
          if (names.length === fns.length) { // 判断是否所有任务都结束了
            drive(names)
          }
        })
      }
    }
    
    /**
     * 方法2:利用Promise + async/await来控制异步(并发)流程
     * 每一个人相当于一个异步任务,最后开车的步骤需要在每个异步任务都完成了之后才进行,所以这其实是一种异步流程控制。
     * 所以方法1是不合理的,因为“是否要开车”这个任务,是独立于任何一个异步任务之外的,按理来说不应该由每一个都进行判断。
     * 故要借助Promise.all来对单个任务、全局任务解耦。
     */
    var driveCustomers = async (...fns) => {
      let names = [] // 保存结果,对于每个异步任务来说是"全局"变量
      let promises = fns.map(fn => {
        return new Promise((resolve, reject) => {
          fn((name) => {
            names.push(name)
            resolve()
          })
        })
      })
      await Promise.all(promises)
      drive(names)
    }
    

  • 0

    @ScriptOJ 这样为什么不行呢?

    const driveCustomers = (...fns) => {
        fns = fns.reverse();
        new Promise((resolve, reject) => {
            let arr = [];
            function cb(name){
                arr.push(name);
                if(arr.length < fns.length){
                  fns[arr.length](cb);
                }else{
                  resolve(arr);
                }
              }
            fns[0](cb);
        }).then((arr) => {
          drive(arr)
        })
    }
    

登录后回复
 

与 ScriptOJ 的连接断开,我们正在尝试重连,请耐心等待