简体   繁体   English

承诺已解决,但代码在等待中停止

[英]Promise is resolved but code stops in await

I followed Mozilla's docs .我跟着 Mozilla's docs I created a function with a Promise inside.我创建了一个内部带有Promise的函数。 The Promise is resolved when the selector appears on the page (if not, the function runs again). The Promise is resolved when the selector appears on the page (if not, the function runs again). Then the code should continue after await :然后代码应该在await之后继续:

;(async () => {
  const titleSel = '.playbackSoundBadge__titleLink'
  document.querySelector(titleSel).click()
  const moreSel = 'button[title="More"]'
  await waitForEl(moreSel)
  console.log('after await')

  function waitForEl(selector) {
    return new Promise(resolve => {
      console.log(selector)
      if (document.querySelector(selector)) {
        console.log('resolved')
        resolve('resolved')
      } else {
        console.log('rejected')
        setTimeout(() => {
          waitForEl(selector)
        }, 100)
      }
    })
  }
})()

But strangely, 'resolved' is logged.但奇怪'resolved'是,记录了'resolved' But the code after await doesn't run.但是await之后的代码没有运行。 In other words, 'after await' is never logged.换句话说,永远不会记录'after await'

Why is this, and how to fix it?这是为什么,以及如何解决?

But strangely, 'resolved' is logged.但奇怪的是,记录了“已解决”。
... ...
Why is this为什么是这样

waitForEl is called "recursively" (it schedules a call of itself via setTimeout ). waitForEl被称为“递归”(它通过setTimeout调度自己的调用)。 Every call to waitForEl creates a promise, so you are creating multiple promises.waitForEl每次调用都会创建一个承诺,因此您正在创建多个承诺。 The 'resolved' you see in the console is from one of those promises.在“解决”你在控制台看到的是那些承诺之一 You should also see one or more 'reject' messages.您还应该看到一条或多条“拒绝”消息。

The problem is that the "parent"/"top" promise is never resolved, because are not doing anything with the return value here:问题是“父”/“顶”承诺永远不会得到解决,因为这里没有对返回值做任何事情:

waitForEl(selector)

The function returns a promise, but you are not doing anything with it, thus never resolving the promise that called this function.该函数返回一个promise,但你没有对它做任何事情,因此永远不会解析调用这个函数的promise。

An easy solution would be一个简单的解决方案是

waitForEl(selector).then(resolve)

But that also means you are creating promises recursively.但这也意味着您正在递归地创建承诺。 It seems unnecessary to do this.似乎没有必要这样做。 Just define a simple function inside the promise that calls itself:只需在调用自身的 Promise 中定义一个简单的函数:

 function waitForEl(selector) {
    return new Promise(resolve => {
      console.log(selector)
      (function check()
        if (document.querySelector(selector)) {
          console.log('resolved')
          resolve('resolved')
        } else {
          console.log('rejected')
          setTimeout(check, 100);
        }
      }());
    })
  }

You should still add some condition that will reject the promise after some time, so it doesn't call setTimeout forever.您仍然应该添加一些条件,在一段时间后拒绝承诺,因此它不会永远调用setTimeout

You have to pass waitForEl(selector) to resolve :您必须通过waitForEl(selector)resolve

 ;(async () => { const moreSel = '.more' await waitForEl(moreSel) console.log('after await') function waitForEl(selector) { return new Promise(resolve => { console.log(selector) if (document.querySelector(selector)) { console.log('resolved') resolve('resolved') } else { console.log('rejected') setTimeout(() => { resolve(waitForEl(selector)) // here }, 1000) } }) } })() const btn = document.createElement("button"); btn.textContent = "add more"; const more = document.createElement("div"); more.textContent = "more"; more.classList.add("more"); btn.addEventListener("click", () => { document.body.appendChild(more); }); document.body.appendChild(btn);

In your code await waitForEl(moreSel) was never settled thus the log below couldn't be executed.在您的代码中await waitForEl(moreSel)从未解决,因此无法执行下面的日志。 If you pass a promise to resolve , the original promise will "bind" its fate to the passed one.如果你传递了一个 promise 来resolve ,那么原来的 promise 将把它的命运“绑定”到通过的那个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM