Promiseとリトライ
HTML
<div>
タスク成功率: <input type="number" id="successRate" max="100" min="0" value="5">%
</div>
<div>
リトライ回数: <input type="number" id="retryCount" max="100000" min="0" value="10">回
</div>
<div>
リトライ実装: <select id="retryImpl">
<option value="none">なし</option>
<option value="forloop1">for文1(ディレイなし)</option>
<option value="forloop2">for文2(ディレイ・キャンセル実装、不具合あり)</option>
<option value="forloop3">for文3(ディレイ・キャンセル実装)</option>
<option value="recursive1">再帰1(無限リトライ、ディレイ・キャンセル実装)</option>
<option value="recursive2">再帰2(有限リトライ、ディレイ・キャンセル実装)</option>
</select>
</div>
<div>
ディレイ: <input type="number" id="baseSleepMillis" max="1000" min="0" value="100">ms * リトライ回数
</div>
<div>
最大ディレイ: <input type="number" id="maxSleepMillis" max="60000" min="0" value="1000">ms
</div>
<div>
<button id="start">実行</button>
<button id="cancel" disabled="disabled">リトライキャンセル</button>
</div>
<div>
<textarea id="console" rows="20" cols="80" placeholder="ここに処理結果が出力されます" readonly></textarea>
</div>
JavaScript
const stopWatch = (() => {
let startTime = new Date().getTime();
return {
getTimeStamp() {
const current = new Date().getTime();
const time = current - startTime;
startTime = current;
return "+" + Math.floor(time / 1000) + "." + (("" + (time % 1000)).padStart(3, '0'));
},
clear() {
startTime = new Date().getTime()
}
}
})();
const clearLog = function() {
document.getElementById('console').innerHTML = "";
stopWatch.clear();
};
const printLog = function(...args) {
document.getElementById('console').innerHTML += `${stopWatch.getTimeStamp()}: ${args.join(' ')}\n`;
};
function sleepAsync(milliseconds) {
return new Promise((r) => setTimeout(r, milliseconds))
}
function doTaskAsync(successRate) {
return new Promise((resolve, reject) => {
setTimeout(() => {
printLog("[Task]", "processing...")
if (Math.random() < successRate / 100.0) {
resolve("SUCCESS");
} else {
reject("FAILED");
}
}, 0);
})
}
const retryImplements = {
"none": function(func) {
return func();
},
"forloop1": function(func, retryCount = 5) {
let promise = func();
for (let i = 1; i <= retryCount; ++i) {
promise = promise.catch(func)
}
return promise;
},
"forloop2": function(func, retryCount = 5, retryActionFunction = () => Promise.resolve()) {
let promise = func();
for (let i = 1; i <= retryCount; ++i) {
promise = promise.catch((...rejectArgs) => retryActionFunction(i, rejectArgs).then(func)) // NG!!
}
return promise;
},
"forloop3": function(func, retryCount = 5, retryActionFunction = () => Promise.resolve()) {
return new Promise((resolve, reject) => {
let promise = func();
for (let i = 1; i <= retryCount; ++i) {
promise = promise.catch((...rejectArgs) => retryActionFunction(i, rejectArgs).then(func, reject))
}
promise.then(resolve, reject);
})
},
"recursive1": function(func, dummy =...