【问题标题】:Waiting for an element to be in the DOM using promises or generator functions使用 Promise 或生成器函数等待元素进入 DOM
【发布时间】:2017-12-12 14:51:47
【问题描述】:

我想要实现的是能够在检查元素当前是否在 DOM 中时使用 Promise。我的想法是远离setTimeOut,但真正使用window.requestAnimationFramesetTimeOut 完全相同,只是性能更高一点。

const doCheck = function(selector){
    if (document.querySelector(selector) === null) {
        window.requestAnimationFrame(function () {
            doCheck(selector);
        });
    } else {
        return true;
    }
};

export default function checkElement(selector) {
    return new Promise(res => {
        doCheck(selector);
        res(true);
    })
}

但当然这不能工作,主要问题是你在选择器不存在时调用另一个函数的事实,我如何用承诺封装这一点?似乎是你不能做这样的事情。

【问题讨论】:

  • 你为什么要从 DOM 中获取这些信息?将元素添加到 DOM 的代码应该为您提供该承诺。
  • 除了@Bergi 的评论之外,为什么您究竟需要加载raf 进行这样的轮询工作,例如每秒创建60 个承诺等。您可以使用Mutation Observer,这似乎是正确的当你关注的东西在 DOM 中发生变化时采取行动的方式。 (比如当一个节点被附加到一个父节点等时)或mutation events 但我认为突变事件存在性能问题并且也贬值有利于突变观察者。

标签: javascript ecmascript-6 promise


【解决方案1】:

您的doCheck 函数是异步的,但既不接受回调也不返回承诺。 checkElement 中的承诺立即得到解决。

@Amit 的回答展示了如何传递回调(并使用它而不是 return),以下是如何使用 Promise 正确执行此操作:

function rafAsync() {
    return new Promise(resolve => {
        requestAnimationFrame(resolve);
    });
}

export default function checkElement(selector) {
    if (document.querySelector(selector) === null) {
        return rafAsync().then(() => checkElement(selector));
    } else {
        return Promise.resolve(true);
    }
}

既然你在谈论生成器函数,我假设你想使用async/await。您可以递归地执行此操作:

export default async function checkElement(selector) {
    if (document.querySelector(selector) === null) {
        await rafAsync();
        return checkElement(selector);
    } else {
        return true;
    }
}

或迭代:

export default async function checkElement(selector) {
    while (document.querySelector(selector) === null) {
        await rafAsync()
    }
    return true;
}

【讨论】:

  • 我的大脑放屁时间......我跑进了一个兔子洞,我这辈子什么都做不了,哈哈,谢谢你:D
【解决方案2】:

您可以发送您的解析函数并在完成后调用它

const doCheck = function(selector,resolve){
    if (document.querySelector(selector) === null) {
        window.requestAnimationFrame(function () {
            doCheck(selector,resolve);
        });
    } else {
        resolve(true);
    }
};


export default function checkElement(selector) {
    return new Promise(res => {
        doCheck(selector,res);
       
    })
}

【讨论】:

    【解决方案3】:
        doCheck(selector);
        res(true);
    

    所以在上面的第一行你开始轮询元素。

    然后你立即解决这个承诺。

    那行不通。

    只有在找到元素时才需要解决承诺

    即在这一行:

       return true;
    

    【讨论】:

      猜你喜欢
      • 2015-07-24
      • 2016-12-18
      • 1970-01-01
      • 2021-10-04
      • 1970-01-01
      • 1970-01-01
      • 2019-03-31
      • 2020-03-09
      • 2017-11-20
      相关资源
      最近更新 更多