2017-12-11 5 views
3

Ich habe eine forEach Schleife, die Daten in einem Array verarbeitet. Irgendwo in der Mitte dieser Schleife muss ich auf eine Änderung in einem DOM-Element warten, diese Änderung ergreifen, sie verarbeiten und nur dann kann ich mit der Verarbeitung des Arrays fortfahren.JavaScript: Wie kann ich async/await verwenden, um auf etwas zu warten, das in MutationObserver passiert?

Ich hoffe, dies in der Konsole zu sehen:

Preparing "aaa" 
Waiting for result on "aaa" 
Processing result on "aaa": <random number> 
Got result for "aaa": <random number>something` 

Und das gleiche für jedes Element in stuffToProcess Array im Code-Snippet. Es ist ein vereinfachtes Beispiel für den Code.

Mir ist klar, dass ähnliche Fragen unzählige Male zuvor gestellt und beantwortet wurden, aber nachdem ich viele von ihnen durchgelesen habe und viele verschiedene Dinge stundenlang ausprobiert habe, kann ich das immer noch nicht herausfinden.

function dummy() { 
 
    $('#trackMe').text(Math.random()); 
 
} 
 

 
async function doWork(stuffToProcess) { 
 
    let target = $('#trackMe')[0]; 
 
    let config = { attributes: true, childList: true, characterData: true, values: true }; 
 
    
 
    let observer = new MutationObserver(function(mutations,item) { 
 
    console.log('Processing result on "%s": %s', item, target.innerText); 
 
    item = item + 'something'; 
 
    return new Promise(resolve => { 
 
     resolve(item); 
 
    }); 
 
    }); 
 

 
    observer.observe(target, config); 
 

 
    stuffToProcess.forEach(async function(item) { 
 
    console.log('Preparing "%s"', item); 
 
    console.log('Waiting for result on "%s"', item); 
 
    let change = await observer(item); 
 
    //^^^ this needs to "await" for data from observer before the loop continues 
 
    console.log('Got result for "%s": %s', item, change); 
 
    }); 
 

 
    //observer.disconnect(); 
 

 
} 
 

 
doWork(['aaa', 'bbb', 'ccc']);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<p id="trackMe">No changes yet</p> 
 
<button onclick="dummy()">Click me to change</button>

+0

Das Versprechen Konstruktor sollte außerhalb des Beobachters Konstruktor erstellt werden, lösen sollte drin sein. – wOxxOm

+0

Aber wie kann ich dann die forEach-Schleife auf Daten vom Beobachter warten lassen, wenn der Beobachter diese Daten nicht "zurückschieben" kann? Ist es möglich, den gesamten Beobachter in eine asynchrone Funktion einzubinden und diese Funktion in der forEach-Schleife aufzurufen? Ich habe das auch schon vorher probiert, aber der Code lief einfach weiter und ich bekam die Antworten vom Beobachter am Ende ... Ich bin normalerweise mehr auf der Systemadministratorseite, weniger Programmierung, also mache ich hier wahrscheinlich etwas sehr falsches ... :) – Brane

+0

ES7 Async-Generator-Funktion könnte helfen, rate ich. – wOxxOm

Antwort

1

Nun, schaffte ich es irgendwie zu lösen. Wahrscheinlich nicht die sauberste Lösung, also wenn jemand irgendwelche Verbesserungen diesbezüglich empfiehlt, werde ich gerne die Lösung/upvote Ihre Antwort bearbeiten.

function dummy() { 
 
    $('#trackMe').text(Math.random()); 
 
} 
 

 
async function doWork(stuffToProcess) { 
 
    let target = $('#trackMe')[0]; 
 
    let config = { 
 
    attributes: true, 
 
    childList: true, 
 
    characterData: true, 
 
    values: true 
 
    }; 
 

 
    let observer; 
 

 
    function isItDone(item) { 
 
    return new Promise(resolve => { 
 

 
     observer = new MutationObserver(function(mutations) { 
 
     console.log('Processing result on "%s": %s', item, target.innerText); 
 
     result = target.innerText + 'something'; 
 
     resolve(result); 
 
     }); 
 

 
     observer.observe(target, config); 
 
    }); 
 
    } 
 

 

 
    for (index in stuffToProcess) { 
 
    console.log('Preparing "%s"', stuffToProcess[index]); 
 
    console.log('Waiting for result on "%s"', stuffToProcess[index]); 
 

 
    let change = await isItDone(stuffToProcess[index]); 
 
    observer.disconnect(); 
 

 
    console.log('Got result for "%s": %s', stuffToProcess[index], change); 
 
    } 
 
} 
 

 
doWork(['aaa', 'bbb', 'ccc']);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<p id="trackMe">No changes yet</p> 
 
<button onclick="dummy()">Click me to change</button>

Verwandte Themen