Skip to content

字节:输出以下代码运行结果,为什么?如果希望每隔 1s 输出一个结果,应该如何改造?注意不可改动 square 方法 #69

Open

Description

@sisterAn
const list = [1, 2, 3]
const square = num => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(num * num)
    }, 1000)
  })
}

function test() {
  list.forEach(async x=> {
    const res = await square(x)
    console.log(res)
  })
}
test()

Activity

  1. sisterAn commented on Jun 21, 2020

    @sisterAn
    OwnerAuthor

    1s 后同时打印 1、4、9

    原因:使用 promise 或 async 函数作为 forEach() 等类似方法的 callback 参数并不会等待异步的执行

    如果我们希望每隔 1s 输出一个结果,方法有:

    • 一个简单的 for 循环
    • for…of / for…in 循环
    • 利用 promise 的链式调用

    解法一:for 循环

    async function test() {
        for(let i = 0; i<list.length; i++) {
            const res = await square(list[i])
        	console.log(res)
        }
    }
    test()

    解法二:for…in / for…of

    for...in

    async function test() {
        for(let i in list) {
            const res = await square(list[i])
        	console.log(res)
        }
    }
    test()

    for...of

    async function test() {
        for(let x of list) {
            const res = await square(x)
        	console.log(res)
        }
    }
    test()

    解法三:利用 promise 的链式调用

    function test() {
        let promise = Promise.resolve()
        list.forEach(x=> {
            promise = promise.then(() => square(x)).then(console.log)
        })
    }
    test()
  2. 7777sea commented on Jun 22, 2020

    @7777sea

    运行结果:一秒后输出1,4,9

    原因:在forEach里面写的callback函数会直接在while循环里面调用

    改造:用for...of 或者for循环代替 forEach

     async function test () {
      for(let x of list) {
        var res = await square(x)
        console.log(res)
      }
    }

    贴一下forEach的源码

    if (!Array.prototype.forEach) {
      Array.prototype.forEach = function(callback, thisArg) {
        var T, k;
        if (this == null) {
          throw new TypeError(' this is null or not defined');
        }
    
        var O = Object(this);
        var len = O.length >>> 0;
    
        if (typeof callback !== "function") {
          throw new TypeError(callback + ' is not a function');
        }
    
        if (arguments.length > 1) {
          T = thisArg;
        }
        k = 0;
    
        while (k < len) {
          var kValue;
          if (k in O) {
            kValue = O[k];
            callback.call(T, kValue, k, O);
          }
          k++;
        }
      };
    }
  3. knightgao commented on Jun 22, 2020

    @knightgao

    运行结果,直接输出1 4 9
    原因:是同步代码,直接执行了
    代码:

    async function test() {
      for await (const x of list) {
        const res =await  square(x)
        console.log(res)
      }
    }
    test()

    遍历异步的循环

  4. xyj626553989 commented on Jun 22, 2020

    @xyj626553989

    运行结果,直接输出1 4 9
    原因:用了递归调用
    代码:

    const list = [1, 2, 3]
    const square = num => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(num * num)
            }, 1000)
        })
    }
    async function test(index = 0) {
        const res = await square(list[index])
        console.log(res)
        if (list[++index]) {
            test(index)
        }
    }
    test()
  5. z253573760 commented on Feb 2, 2021

    @z253573760
    const list = [1, 2, 3];
    const square = (num) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(num * num);
        }, 1000);
      });
    };
    
    function test() {
      list.forEach(async (x) => {
        const res = await square(x);
        console.log(res);
      });
    }
    test();
    
    function test2() {
      let p = Promise.resolve();
      for (const item of list) {
        p = p.then(() => square(item).then(console.log));
      }
    }
    test2();
    
    async function test3() {
      for (const item of list) {
        const res = await square(item);
        console.log(res);
      }
    }
    test3();
    
    function test4() {
      class Schedule {
        constructor() {
          this.list = [];
          this.status = "waiting";
        }
        add(fn) {
          this.list.push(fn);
          if (this.status === "waiting") {
            this.run();
          }
        }
        async run() {
          this.status = "running";
          while (this.list.length) {
            const task = this.list.shift();
            await task();
          }
          this.status = "waiting";
        }
      }
      const schedule = new Schedule();
      for (const item of list) {
        schedule.add(() => square(item).then(console.log));
      }
    }
    test4();
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions