元ネタ:「進捗・どう・です・か」をランダムに表示し「進捗どうですか」が完成したら煽ってくるプログラムをES6で書いてみる
メッセージがリアルタイムに伸びていくようにしてみた。
- TypeScript で書いたが、関数の引数と返値に型情報を追加しただけなので、「JavaScript は分かるけど TypeScript は分からない」という方でも(
: string
とか: number
とかを無視していただければ)理解できるはず。 - コンソール出力だと改行なしにはできなさそうなので、HTML に出力するようにした。
- async/await で遅延処理を入れることで徐々にメッセージが伸びるようにした。
- CodePen を埋め込んでみたが、一定時間経つと処理が止まってしまう(最後まで行かないことがある)ようだ。
const WORDS = Object.freeze(["進捗", "どう", "です", "か"]);
const SEQUENCE_FINISH = "???";
const SHOUT = `_人人人人人人人_
>進捗どうですか<
 ̄Y^Y^Y^Y^Y^Y^Y ̄`;
const SEQUENCE_INTERVAL = 10;
const SHOUT_DELAY = 1500;
const SEQUENCE_CONTAINER_ID = "sequence_container";
const SHOUT_CONTAINER_ID = "shout_container";
(async () => {
await appendWordSequenceAsync(
WORDS, SEQUENCE_CONTAINER_ID, SEQUENCE_INTERVAL);
appendText(SEQUENCE_CONTAINER_ID, SEQUENCE_FINISH);
await timeoutAsync(SHOUT_DELAY);
appendMultilineText(SHOUT_CONTAINER_ID, SHOUT);
})();
async function appendWordSequenceAsync(
words: ReadonlyArray<string>,
parentElementId: string,
interval: number
): Promise<void> {
let progress = 0;
while (true) {
const index = getRandomInt(0, words.length);
const word = words[index];
appendText(parentElementId, word);
if (progress !== index) {
progress = 0;
}
if (progress === index) {
++progress;
if (progress >= words.length) {
break;
}
}
await timeoutAsync(interval);
}
}
function appendMultilineText(
parentElementId: string,
text: string
): void {
text.split("\n").forEach(line => {
appendText(parentElementId, line);
appendBr(parentElementId);
});
}
function appendText(
parentElementId: string,
text: string
): void {
const parent = ensureElement(parentElementId);
const textNode = document.createTextNode(text);
parent.appendChild(textNode);
}
function appendBr(parentElementId: string): void {
const br = document.createElement("br");
ensureElement(parentElementId).append(br);
}
function ensureElement(elementId: string): HTMLElement {
const existing = document.getElementById(elementId);
if (existing) { return existing; }
const newElement = document.createElement("div");
newElement.id = elementId;
document.body.appendChild(newElement);
return newElement;
}
function getRandomInt(
rangeBegin: number,
rangeEnd: number
): number {
return rangeBegin
+ Math.floor(Math.random() * (rangeEnd - rangeBegin));
}
function timeoutAsync(delay: number): Promise<void> {
return new Promise(resolve =>
setTimeout(() => resolve(), delay)
);
}
See the Pen 進捗どうですか??? by sdkei (@sdkei) on CodePen.