Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
sisterAn opened this issue Jun 21, 2020 · 5 comments

Comments

@sisterAn
Copy link
Owner

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()
@sisterAn
Copy link
Owner Author

sisterAn commented Jun 21, 2020

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

原因:使用 promiseasync 函数作为 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()

@7777sea
Copy link

7777sea commented Jun 22, 2020

运行结果:一秒后输出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++;
    }
  };
}

@knightgao
Copy link

knightgao commented Jun 22, 2020

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

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

遍历异步的循环

@xyj626553989
Copy link

xyj626553989 commented Jun 22, 2020

运行结果,直接输出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()

@z253573760
Copy link

z253573760 commented Feb 2, 2021

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
Projects
None yet
Development

No branches or pull requests

5 participants