JS程序如何知道函数内部setTimeout中的时间?[复制]

how JS program knows the time in setTimeout inside a function? [duplicate]

提问人:Rocko 提问时间:11/9/2023 最后编辑:DavidRocko 更新时间:11/9/2023 访问量:66

问:

const p1 = new Promise((resolve,reject) => {
  setTimeout(()=>{
    resolve("xxx");
  }, 5000)
});

const p2 = new Promise((resolve,reject) => {
  setTimeout(()=>{
    resolve("xx");
  }, 10000)
});


async function he() {
  console.log("start"); 

  const s1 = await p1;
  console.log("Rome");

  const s2 = await p2;
  console.log("Paris");
}

he();
console.log("Hey bro")

问题 - 现在,当程序执行开始时,它会立即打印“start”,然后打印“hey bro”,JS 不会等待等待完成并继续执行。现在,当 JS 在 he() 中遇到 p1 时,它会在 5 秒后打印“Rome”,然后在接下来的 5 秒后打印 Paris。

现在我的问题是,为什么它在 10 秒后没有打印巴黎?p2 的计时器是如何在达到 p2 初始化之前启动的?或者是吗?我知道当它遇到 p1 时,它会停止在调用堆栈中执行 he() func,这是它以某种方式开始在幕后执行 s2 的时候吗?

JavaScript 性能 步 async-await async.js

评论

1赞 Rory McCrossan 11/9/2023
Now my question is, why didn't it print Paris after 10 sec?出于同样的原因,你看到的是 - 异步调用没有阻塞,因此下一个函数调用会立即发生。hey brostart
0赞 Rocko 11/9/2023
但据我所知,也许一旦程序遇到 await 的承诺,它就会从 callstack 中删除该函数!所以,这就是为什么当遇到 p1 时,它会立即打印“嘿兄弟”,但是如果我学到的是正确的,那么 p2 的执行是如何在 p1 结束之前开始的呢?Becz func 本身不在调用堆栈中
2赞 slebetman 11/9/2023
因为你同时启动了两个计时器。如果要在第一次之后启动第二个计时器,请替换为(与)相同,然后替换为const p1 = new Promise(...const p1 = () => new Promise(...p2await p1await p1()
4赞 slebetman 11/9/2023
请注意,回调不会延迟。它是同步执行的(不是异步的)。所以你创建得太早了new Promise()p2
2赞 slebetman 11/9/2023
你痴迷在错误的地方。是的,js 逐行执行。这就是为什么之前执行的原因.你太痴迷于不是创建的地方。你看错了地方。const p1 = new Promise()const p2 = new Promise()await p1setTimeout()

答:

0赞 Alexander Nied 11/9/2023 #1

因为它是异步的,而你没有 ing .你不能在顶层,但如果你把整个程序嵌套在一个函数中,你可以看到它的行为符合我相信你的期望。awaithe()awaitasyncawaithe()

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("xxx");
  }, 5000)
});

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("xx");
  }, 10000)
});


async function he() {
  console.log("start");

  const s1 = await p1;
  console.log("Rome");

  const s2 = await p2;
  console.log("Paris");
}


async function runProgram() {
  await he();
  console.log("Hey bro")
}

runProgram();

此外,值得注意的是,您不是在调用,而是 - 它们是在您分配它们的那一刻开始倒计时的承诺,因此即使您没有调用,它们也会在初始化和分配后的几秒钟内解析。p1p2he()510

评论

0赞 Rocko 11/9/2023
你能回答我这个问题吗?“但据我所知,也许一旦程序遇到 await 的承诺,它就会从 callstack 中删除该函数!所以,这就是为什么当遇到 p1 时,它会立即打印“嘿兄弟”,但是如果我学到的是正确的,那么 p2 的执行是如何在 p1 结束之前开始的呢?Becz func 本身不在调用堆栈中”
0赞 Alexander Nied 11/9/2023
@Rocko我不确定我是否完全理解您的问题,但您似乎对开始第一次超时后如何继续执行感到困惑。我认为你在两个方面感到困惑:1)你实际上并没有调用,而且 - 你在定义它们的那一刻就启动了它们的计时器,因为这就是你编写它的方式,以及 2)尽管 JS 可能不是多线程的,但它仍然能够异步执行,并且诸如此类的事情的全部目的是允许执行不受限制地继续执行,同时等待执行传递给的内容(除非您)。p1p2setTimeoutsetTimeoutawait
1赞 David 11/9/2023 #2

p2 的计时器是如何在达到 p2 初始化之前启动的?

当你这样做时,它没有开始:

const s2 = await p2;

当您执行此操作时,它就开始了:

const p2 = new Promise((resolve,reject) => {
  setTimeout(()=>{
    resolve("xx");
  }, 10000)
});

也就是说,两个计时器/承诺都立即启动。你在函数中所做的就是等待这些承诺的结果,但它们已经开始了。he

第一个计时器是 5 秒,第二个计时器是 10 秒。它们同时启动并同时运行。

你可以通过不定义承诺来实现你正在寻找的结果,直到你想等待它们。例如:

async function he() {
  console.log("start"); 

  const s1 = await new Promise((resolve,reject) => {
    setTimeout(()=>{
      resolve("xxx");
    }, 5000)
  });
  console.log("Rome");

  const s2 = await new Promise((resolve,reject) => {
    setTimeout(()=>{
      resolve("xx");
    }, 10000)
  });;
  console.log("Paris");
}

he();
console.log("Hey bro")

或者通过定义创建/返回 promise 的函数,而不是定义 promise 本身:

const p1 = () => new Promise((resolve,reject) => {
  setTimeout(()=>{
    resolve("xxx");
  }, 5000)
});

const p2 = () => new Promise((resolve,reject) => {
  setTimeout(()=>{
    resolve("xx");
  }, 10000)
});


async function he() {
  console.log("start"); 

  const s1 = await p1();
  console.log("Rome");

  const s2 = await p2();
  console.log("Paris");
}

he();
console.log("Hey bro")