I'm currently looking at async-await
in C#, and noticed similarities to JavaScript promises. Looking into this I see that JavaScript is also going to support async-await
statements, and that there are similarities between this and promises (look at this blog post for example).
On a whim, I wondered what JavaScript's implementation of async-await
was and found this question (Java Equivalent of C# async/await?).
The accepted answer suggests that async-await
(and by extension, I guess, promises) are implementations of a 'state machine'.
Question: What is meant by a 'state machine' in terms of promises, and are JavaScript promises parable to C#'s async-await
?
I'm currently looking at async-await
in C#, and noticed similarities to JavaScript promises. Looking into this I see that JavaScript is also going to support async-await
statements, and that there are similarities between this and promises (look at this blog post for example).
On a whim, I wondered what JavaScript's implementation of async-await
was and found this question (Java Equivalent of C# async/await?).
The accepted answer suggests that async-await
(and by extension, I guess, promises) are implementations of a 'state machine'.
Question: What is meant by a 'state machine' in terms of promises, and are JavaScript promises parable to C#'s async-await
?
-
I recently read a question on here that asked about the implementation of .Net
yield
andasync/await
. The answer discussed both in terms of state machines along with some pseudo code. I'm not sure if it was a recent question though. (I might have navigated to it by chance). It wouldn't necessarily answer your question but it was a very good read on the matter, I just can't seem to find it (searching on my phone). Perhaps someone with better search skills can locate it knowing the subject matter. – pinkfloydx33 Commented Feb 23, 2017 at 10:07 - This is how I came here twitter./rauschma/status/1026954063924084737 (Axel Rauschmayer twitting among others about target of transpilation for NPM packages) – Marecky Commented Aug 8, 2018 at 20:26
1 Answer
Reset to default 9JavaScript promises are parable to C# Task
objects which have a ContinueWith
function that behaves like .then
in JavaScript.
By "state machines" it is means that they are typically implemented by a state and a switch statement. The states are places the function can be at when it runs synchronously. I think it's better to see how such a transformation works in practice. For example let's say that your runtime only understands regular functions. An async function looks something like:
async function foo(x) {
let y = x + 5;
let a = await somethingAsync(y);
let b = await somethingAsync2(a);
return b;
}
Now, let's look at all the places the function can be when it executes a step synchronously:
async function foo(x) {
// 1. first stage, initial
let y = x + 5;
let a = await somethingAsync(y);
// 2. after first await
let b = await somethingAsync2(a);
// 3. after second await
return b;
// 4. done, with result `c`.
}
Now, since our runtime only understands synchronous functions - our piler needs to do something to make that code into a synchronous function. We can make it a regular function and keep state perhaps?
let state = 1;
let waitedFor = null; // nothing waited for
let waitedForValue = null; // nothing to get from await yet.
function foo(x) {
switch(state) {
case 1: {
var y = x + 5;
var a;
waitedFor = somethingAsync(y); // set what we're waiting for
return;
}
case 2: {
var a = waitedForValue;
var b;
waitedFor = somethingAsync(a);
return;
}
case 3: {
b = waitedFor;
returnValue = b; // where do we put this?
return;
}
default: throw new Error("Shouldn't get here");
}
}
Now, it's somewhat useful, but doesn't do anything too interesting - we need to actually run this as a function. Let's put the state in a wrapper and automatically run the promises when they're resolved:
function foo(x) { // note, not async
// we keep our state
let state = 1, numStates = 3;
let waitedFor = null; // nothing waited for
let waitedForValue = null, returnValue = null; // nothing to get from await yet.
// and our modified function
function stateMachine() {
switch(state) {
case 1: {
var y = x + 5;
var a;
waitedFor = somethingAsync(y); // set what we're waiting for
return;
}
case 2: {
var a = waitedForValue;
var b;
waitedFor = somethingAsync(a);
return;
}
case 3: {
b = waitedFor;
returnValue = b; // where do we put this?
return;
}
default: throw new Error("Shouldn't get here");
}
// let's keep a promise for the return value;
let resolve, p = new Promise(r => resolve = r); // keep a reference to the resolve
// now let's kickStart it
Promise.resolve().then(function pump(value) {
stateMachine();
state++; // the next state has progressed
if(state === numStates) resolve(returnValue); // return the value
return Promise.resolve(waitedFor).then(pump);
});
return p; // return the promise
}
Effectively, the Promise.resolve().then(...
part calls the stateMachine and waits for the value that's being awaited every time until it is at the final state at which point it resolves the (returned beforehand) promise.
This is effectively what Babel or TypeScript do with your code too. What the C# piler does is very close - with the biggest difference is that it's put in a class.
Note we are ignoring conditionals, exceptions and loops here - it makes things a little bit more plicated but not much harder (you just need to handle each case separately).
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742347262a4426798.html
评论列表(0条)