Christopher Pitt
Writer and coder, working at ringier.co.za
const items = ["apple", "orange", "strawberry"];
for (let i = 0; i < items.length; i++) {
console.log(items[i]);
}
*unless you're changing the array between look-ups
const Iterator = function () {
let i = 0;
const items = ["apple", "orange", "strawberry"];
const done = function () {
return i >= items.length;
};
return {
done,
next: function () {
i++;
return items[i - 1];
}
};
};
const iterator = Iterator();
while (!iterator.done()) {
console.log(iterator.next());
}
function* (items) {
for (let i = 0; i < items.length; i++) {
yield items[i];
}
}
const Generator = function () {
const items = ["apple", "orange", "strawberry"];
return {
[Symbol.iterator]: function* () {
for (let i = 0; i < items.length; i++) {
yield items[i];
}
}
};
};
const generator = Generator();
for (const next of generator) {
console.log(next);
}
class Task {
constructor(generator) {
this.generator = generator();
}
tick() {
return this.generator.next();
}
}
class Runner {
tasks = [];
add(task) {
this.tasks.push(task);
}
tick() {
const task = this.tasks.shift();
if (!task) {
return false;
}
if (!task.tick().done) {
this.add(task);
}
return this.tasks.length;
}
}
const runner = new Runner();
runner.add(
new Task(function* () {
for (let i = 0; i < 5; i++) {
console.log(`first task is ${i}`);
yield;
}
})
);
runner.add(
new Task(function* () {
for (let i = 0; i < 3; i++) {
console.log(`second task is ${i}`);
yield;
}
})
);
while (runner.tick());
[Log] first task is 0
[Log] second task is 0
[Log] first task is 1
[Log] second task is 1
[Log] first task is 2
[Log] second task is 2
[Log] first task is 3
[Log] first task is 4
const ayyysync = function (generatorFactory) {
return generatorFactory();
};
const ayyywait = function (generatorInstance) {
let previous = undefined;
while (true) {
const next = generatorInstance.next();
if (!next.done) {
previous = next.value;
} else {
break;
}
}
return previous;
};
const task = function () {
return ayyysync(function* () {
for (let i = 0; i < 5; i++) {
console.log(`third task is ${i}`);
yield "done";
}
});
};
const result = ayyywait(task());
const task = function () {
return ayyysync(function* () {
// ...
});
};
const out = ayyywait(task());
vs.
const task = async function() {
// ...
};
const out = await task();
const [_, changeSets] = await Promise.all([
clearCache(),
getChangeSets({ state: published }),
])
await cacheChangeSets(changeSets)
const sleep = function (ms) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(`slept for ${ms}`);
}, ms);
});
};
const task = async function () {
console.log("starting...");
const result = await sleep(100);
console.log(`resulted in ${result}`);
return sleep(200);
};
const task = Awaitable([
function (__previous, __context) {
console.log("starting...");
},
sleep(100),
function (__previous, __context) {
__context["result"] = __previous;
console.log(`resulted in ${__context["result"]}`);
},
sleep(200)
]);
// in the background...
let tasks = [];
setInterval(function () {
let remaining = [];
for (const task in tasks) {
if (task.awaiting && task.awaiting.isResolved) {
task.resume(task.awaiting.value);
}
if (!task.isResolved) {
remaining.push(task);
}
}
tasks = remaining;
}, 0);
*event loop, interrupts, network, fs, threading, promises
*reactphp, amphp
use Psr\Http\Message\ServerRequestInterface;
use React\Http\HttpServer;
use React\Http\Message\Response;
use React\Socket\SocketServer;
$http = new HttpServer(function(ServerRequestInterface $request) {
return new Response(
200,
["Content-Type" => "text/plain"],
"Hello world\n",
);
});
$socket = new SocketServer("127.0.0.1:8080");
$http->listen($socket);
use Amp\Http\Server\HttpServer;
use Amp\Http\Server\RequestHandler\CallableRequestHandler;
use Amp\Http\Server\Response;
use Amp\Http\Status;
use Amp\Loop;
use Amp\Socket\Server;
Loop::run(function() {
$server = new HttpServer(
[Server::listen("127.0.0.1:8080")],
new CallableRequestHandler(function() {
return new Response(
Status::OK,
["content-type" => "text/plain"],
"Hello world\n",
);
})
);
yield $server->start();
});
$task = async function($client) {
$this->prepare($client);
await $update($client);
};
$task = [
($update = $update ?? null),
"fn" => function ($client) use (&$update): \Amp\Promise {
return \Amp\call(function () use (&$update) {
$this->prepare($client);
yield $update($client);
});
}
]["fn"];
slides.com/assertchris/inventing-async-await-september-2021
By Christopher Pitt