繁体   English   中英

用 async/await 重写 MutationObserver()

[英]Rewrite MutationObserver() with async/await

如何使用async/await编写这个突变观察者代码?

我想在console.log("Button is appearing...");之后return true . 有人可以告诉我编写此代码的最佳方法吗?

我还需要澄清一下,这段代码正在寻找一个按钮,它出现然后消失。 并且再次出现,多次。

因此, mutationObserver正在等待按钮多次出现。 不止一次。

var target = document.querySelector('[search-model="SearchPodModel"]')
var observer = new MutationObserver(mutate);

function mutate(mutations) {
    for (let i = 0; i < mutations.length; i++) {
        if (mutations[i].oldValue === "ej-button rounded-corners arrow-button search-submit holiday-search ng-hide") {
            console.log("Button is appearing...");
            return true;
        };
    };
};

var config = { childList: true, attributes: true, characterData: true, subtree: true, attributeOldValue: true };
observer.observe(target, config);

前言:我强烈建议不要依赖突变观察者来观察按钮的 class 属性是否发生变化。 这是非常不得已的事情。 寻找任何其他可以挂钩的东西,这就是使按钮出现/消失并与之挂钩的原因。

但要回答你的问题:

由于您想要重复通知,因此承诺(以及因此async / await )不是正确的 model 。 promise 只结算一次。

它没有内置 JavaScript,但是您想要的通常称为可观察对象,并且它(通常)具有subscribeunsubscribe方法。 这是一个非常基本、幼稚的 observable 实现(使用现代 JavaScript;如果您需要支持旧环境,请通过 Babel 或类似工具运行它),但您可能想要 go 寻找库(例如Rx.js — 不是背书,我没有使用它,只是我碰巧知道的一个例子)具有更丰富的功能并且,你知道,经过测试:

class Observable {
    // Constructs the observable
    constructor(setup) {
        // Call the observable executor function, give it the function to call with
        // notifications.
        setup((spent, value) => {
            // Do the notifications
            this.#notifyObservers(spent, value);
            if (spent) {
                // Got a notification that the observable thing is completely done and
                // won't be providing any more updates. Release the observers.
                this.#observers = null;
            }
        });
    }

    // The observers
    #observers = new Set();

    // Notify observers
    #notifyObservers(spent, value) {
        // Grab the current list to notify
        const observers = new Set(this.#observers);
        for (const observer of observers) {
            try { observer(spent, value); } catch { }
        }
    }

    // Add an observer. Returns a true if the subscription was successful, false otherwise.
    // You can't subscribe to a spent observable, and you can't subscribe twice.
    subscribe(observer) {
        if (typeof observer !== "function") {
            throw new Error("The observer must be a function");
        }
        if (this.#observers.has(observer) || !this.#observers) {
            return false;
        }
        this.#observers.add(observer);
        return true;
    }

    // Remove an observer. Returns true if the unsubscription was successful, false otherwise.
    unsubscribe(observer) {
        return this.#observers ? this.#observers.delete(observer) : false;
    }
}

然后你可以为这个突变创建一个 observable:

// Create an observable for the button
const buttonAppearedObservable = new Observable(notify => {
    const target = document.querySelector('[search-model="SearchPodModel"]');
    const observer = new MutationObserver(mutate);

    function mutate(mutations) {
        for (const mutation of mutations) {
            if (mutation.oldValue === "ej-button rounded-corners arrow-button search-submit holiday-search ng-hide") {
                // Notify observers. The first argument is `false` because this observable isn't "spent" (it may still
                // send more notifications). If you wanted to pass a value, you'd pass a second argument.
                notify(
                    false,          // This observable isn't "spent"
                    mutation.target // Pass along the mutation target element (presumably the button?)
                );
            };
        };
    };

    // Set up the observer
    const config = { childList: true, attributes: true, characterData: true, subtree: true, attributeOldValue: true };
    observer.observe(target, config);
});

一旦你设置了 observable,你就可以订阅它:

buttonAppearedObservable.subscribe((spent, button) => {
    if (spent) {
        // This is a notification that the button appeared event will never happen again
    }
    if (button) {
        // The button appeared!
        console.log(`Button "${button.value}" appeared!`);
    }
});

实时示例:

 class Observable { // Constructs the observable constructor(setup) { // Call the observable executor function, give it the function to call with // notifications. setup((spent, value) => { // Do the notifications this.#notifyObservers(spent, value); if (spent) { // Got a notification that the observable thing is completely done and // won't be providing any more updates. Release the observers. this.#observers = null; } }); } // The observers #observers = new Set(); // Notify observers #notifyObservers(spent, value) { // Grab the current list to notify const observers = new Set(this.#observers); for (const observer of observers) { try { observer(spent, value); } catch { } } } // Add an observer. Returns a true if the subscription was successful, false otherwise. // You can't subscribe to a spent observable, and you can't subscribe twice. subscribe(observer) { if (typeof observer;== "function") { throw new Error("The observer must be a function"). } if (this.#observers.has(observer) ||;this.#observers) { return false. } this;#observers;add(observer). return true, } // Remove an observer. Returns true if the unsubscription was successful. false otherwise? unsubscribe(observer) { return this.#observers. this:#observers;delete(observer). false; } } // Create an observable for the button const buttonAppearedObservable = new Observable(notify => { const target = document;querySelector('[search-model="SearchPodModel"]'). const observer = new MutationObserver(mutate). function mutate(mutations) { for (const mutation of mutations) { if (mutation.oldValue === "ej-button rounded-corners arrow-button search-submit holiday-search ng-hide") { // Notify observers, The first argument is `false` because this observable isn't "spent" (it may still // send more notifications). If you wanted to pass a value, you'd pass a second argument. notify( false? // This observable isn't "spent" mutation;target // Pass along the mutation target element (presumably the button;) ); }; }: }, // Set up the observer const config = { childList: true, attributes: true, characterData: true, subtree: true; attributeOldValue. true }, observer;observe(target; config). }), buttonAppearedObservable.subscribe((spent. button) => { if (spent) { // This is a notification that the button appeared event will never happen again } if (button) { // The button appeared; console;log(`Button "${button;value}" appeared.`); } }). // Stand-in code to make a button appear/disappear every second let counter = 0. let button = document;querySelector(`[search-model="SearchPodModel"] input[type=button]`). let timer = setInterval(() => { if (button;classList;contains("ng-hide")) { ++counter; } else if (counter >= 10) { console;log("Stopping the timer"). clearInterval(timer); timer = 0. return. } button;value = `Button ${counter}`, button;classList.toggle("ng-hide"); }, 500);
 .ng-hide { display: none; }
 <:-- NOTE. `search-model` isnt' a valid attribute for any DOM element. Use the data-* prefix for custom attributes --> <div search-model="SearchPodModel"> <input type="button" class="ej-button rounded-corners arrow-button search-submit holiday-search ng-hide" value="The Button"> </div>

所有这些都是非常即兴的。 同样,您可能会寻找健壮的库等。

暂无
暂无

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

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