2017-12-07 1 views
0

Ich habe im vorherigen Code einige Änderungen vorgenommen und weitere Tests ausgeführt, und ich habe das gleiche Problem erneut (Is it possible continue a stopped async function?). Also diese Frage ist verwandt.Ist es möglich, eine angehaltene Async-Funktion fortzusetzen? (2)

Darüber hinaus funktioniert die vorherige Lösung nicht.

var stop = false; 
 
var pause = false; 
 
var elParrafo = document.getElementById('miParrafo'); 
 

 
function sendPause() { 
 
    pause = true; 
 
} 
 

 
function sendContinue() { 
 
    pause = false; 
 
} 
 

 
function sendStop() { 
 
    stop = true; 
 
} 
 

 
function longWork(ms, char) { 
 
    return new Promise(function(resolve, reject) { 
 
    elParrafo.innerHTML += char; 
 
    setTimeout(resolve, ms); 
 
    }); 
 
} 
 

 
async function doIt() { 
 
    for (var i = 0; i < 666; i++) { 
 
    if (!stop) { 
 
     if (!pause) { 
 
     await longWork(50," > "); 
 
     } 
 
    } else { 
 
     break; 
 
    } 
 
    } 
 
} 
 

 
doIt();
<form class="" action="index.html" method="post"> 
 
    <input type="button" value="Pause" onclick="sendPause()"> 
 
    <input type="button" value="Continue" onclick="sendContinue()"> 
 
    <input type="button" value="Stop" onclick="sendStop()"> 
 
</form> 
 
<p id="miParrafo"></p>

+0

Ich bin nicht sicher, ob Sie verspricht oder 'async await' verstehen. Der von Ihnen gepostete Code könnte mit 'setTimeout' oder' setInterval' viel einfacher erledigt werden. Wenn Sie lange laufenden Code haben, der Ihre Benutzeroberfläche blockiert, sollten Sie Web-Worker verwenden. Info über warum und wie man verspricht: https://stackoverflow.com/a/47678417/1641941 – HMR

Antwort

3

Das Problem tritt auf, wenn Sie die Flags auf true gesetzt. Der asynchrone Code erschöpft den Rest der Schleife, indem er nichts tut, wenn Sie die Flags deaktivieren. Sie können stattdessen mit einigen Versprechen umgehen.

let stop = false; 
 
let isPaused = false; 
 
let resolvePause =() => {}; 
 
let pauseProm = Promise.resolve(); 
 
const elParrafo = document.getElementById('miParrafo'); 
 

 
function sendPause() { 
 
    if(isPaused) return; 
 

 
    isPaused = true; 
 
    pauseProm = new Promise(resolve => resolvePause = resolve); 
 
} 
 

 
function sendContinue() { 
 
    isPaused = false; 
 
    resolvePause(); 
 
} 
 

 
function sendStop() { 
 
    stop = true; 
 
} 
 

 
function longWork(ms, char) { 
 
    return new Promise(function(resolve, reject) { 
 
    elParrafo.innerHTML += char; 
 
    setTimeout(resolve, ms); 
 
    }); 
 
} 
 

 
async function doIt() { 
 
    for (let i = 0; i < 666; i++) { 
 
    if (stop) break; 
 

 
    await pauseProm; 
 
    await longWork(50," > "); 
 
    } 
 
} 
 

 
doIt();
<form class="" action="index.html" method="post"> 
 
    <input type="button" value="Pause" onclick="sendPause()"> 
 
    <input type="button" value="Continue" onclick="sendContinue()"> 
 
    <input type="button" value="Stop" onclick="sendStop()"> 
 
</form> 
 
<p id="miParrafo"></p>

+0

Wow !! Ich muss viel lernen. Vielen Dank!! –

+0

@ kamoroso94 Was genau macht diese Zeile: 'new Promise (resolve => resolvePause = resolve);' Es ist möglich, innerhalb eines Versprechens ohne "resolve" oder "reject" zurückzukehren? – robe007

+0

@ kamoroso94 Können Sie bitte etwas mehr darüber erklären, wie 'sendPause() 'und' sendContinue() 'funktionieren? – robe007

4

Wenn Sie die Aufgabe unterbrechen, müssen Sie es tatsächlich anhalten und warten, bis der Benutzer fortfahren möchte, nicht die Schleife bis zum Ende fortsetzen, aber ohne jede Arbeit zu tun.

var stopped; 
 
var paused; 
 
var waitingContinuations; 
 

 
function sendStart() { 
 
    stopped = false; 
 
    paused = false; 
 
    waitingContinuations = []; 
 
    doIt(); 
 
} 
 

 
function sendPause() { 
 
    paused = true; 
 
} 
 

 
function sendContinue() { 
 
    paused = false; 
 
    for (const cont of waitingContinuations) 
 
    cont(); 
 
    waitingContinuations.length = 0; 
 
} 
 

 
function sendStop() { 
 
    stopped = true; 
 
} 
 

 
async function doIt() { 
 
    document.getElementById('output').textContent = ""; 
 
    for (var i = 0; i < 666; i++) { 
 
    // in places where you might want to abort, put this: 
 
    if (stopped) return; // or throw new Error("stopped"); 
 
    // in places where you might want to pause, put this: 
 
    if (paused) await new Promise(resolve => waitingContinuations.push(resolve)); 
 

 
    await longWork(50, " > "); 
 
    } 
 
} 
 

 
function longWork(ms, char) { 
 
    return new Promise(resolve => { 
 
    document.getElementById('output').textContent += char; 
 
    setTimeout(resolve, ms); 
 
    }); 
 
}
<form> 
 
    <input type="button" value="Start" onclick="sendStart()"> 
 
    <input type="button" value="Pause" onclick="sendPause()"> 
 
    <input type="button" value="Continue" onclick="sendContinue()"> 
 
    <input type="button" value="Stop" onclick="sendStop()"> 
 
</form> 
 
<p id="output"></p>

+0

'neue Versprechen (Auflösung => waitingContinuations.push (auflösen));' Wie ist diese Zeile ohne die Pfeil-Syntax? – robe007

+2

@ robe007 http://babeljs.io/repl/#?code_lz=HYUw7gBACgTg9gWwJYGcQAoYhXANgNxAgF4A-CMAQyQBclgBzAYTmDuAFdK7WUA6AA4cUAC0zY8hAJRSA3EA – Bergi

+0

So ist es möglich, zu 'return' innerhalb eines' Promise' ohne 'resolve' oder' reject'? Warum? – robe007

0

Hier ist eine einfache Lösung, die setInterval verwendet:

var task = (function(){ 
 
    var timer; 
 
    var taskImplementation; 
 
    var max; 
 
    var ms; 
 
    var timesRun = 0; 
 
    var isPaused = false; 
 
    const runTask = function(){ 
 
    if(!isPaused && timesRun<max){ 
 
     taskImplementation(); 
 
     timesRun++; 
 
    }else{ 
 
     clearInterval(timer); 
 
    } 
 
    }; 
 
    const reset = function() { 
 
    timesRun=0; 
 
    isPaused=false;  
 
    }; 
 
    const start = function(){ 
 
    if(timer){ 
 
     stop(); 
 
    } 
 
    reset(); 
 
    timer = setInterval(runTask,ms); 
 
    }; 
 
    const stop = function(){ 
 
    reset(); 
 
    clearInterval(timer); 
 
    }; 
 
    const pause = function(){ 
 
    clearTimeout(timer); 
 
    }; 
 
    const cont = function(){ 
 
    timer = setInterval(runTask,ms);  
 
    }; 
 
    return function(doWhat){ 
 
    taskImplementation = doWhat; 
 
    return function(interval){ 
 
     ms = interval; 
 
     return function(howManyTimes){ 
 
     max = howManyTimes;   
 
     return { 
 
      start:start, 
 
      stop:stop, 
 
      pause:pause, 
 
      continue:cont 
 
     } 
 
     } 
 
    } 
 
    } 
 
})(); 
 
var doWhat = (function(elParrafo){ 
 
    return function(){ 
 
    elParrafo.innerHTML += " > "; 
 
    } 
 
})(document.getElementById('miParrafo')); 
 
var interval =200;//how long to wait between task execution 
 
var howManyTimes = 666;//how many times to repeat task 
 
window.setParrafoTask = task(doWhat)(interval)(howManyTimes);
<form class="" action="index.html" method="post"> 
 
     <input type="button" value="Start" onclick="setParrafoTask.start()"> 
 
     <input type="button" value="Pause" onclick="setParrafoTask.pause()"> 
 
     <input type="button" value="Continue" onclick="setParrafoTask.continue()"> 
 
     <input type="button" value="Stop" onclick="setParrafoTask.stop()"> 
 
     </form> 
 
     <p id="miParrafo"></p>

Verwandte Themen