JSFiddle - React, Tailwind, and code Playground
HTML
<p>
A <tt>Promise</tt> is like a container that will resolve (or not) to a value. This may have already happened, or it may happen in the future.
</p>
<p>
<tt>Promise</tt> can be in one of three states:
</p>
<dl>
<dt>Unresolved</dt>
<dd>The value has not yet been resolved, and will resolve in the future</dd>
<dt>Resolved</dt>
<dd>The value has been resolved can be used immediately</dd>
<dt>Rejected</dt>
<dd>The value has been rejected? Anyway it means there was an error or whatever</dd>
</dl>
<p><tt>Promise</tt> exposes a <tt>then</tt> method that allows a user to <em>bind</em> a function that will handle the resolved value. The function can be bound either before or after the value has actually been resolved.</p>
<p>
<code>
unresolvedPromise.then((value) => {
// do something with value when it's resolved in the future
})
alreadyResolvedPromise.then((value) => {
// do something with value immediately
})
rejectedPromise.then((value) => {
// this promise got rejected, so this function will never get called
// if a promise is unresolved then gets rejected, it will also not
// call functions bound with then
})
</code>
</p>
<p>How does a value actually get provided to a <tt>Promise</tt>? Whoever creates the promise has to call the special <tt>resolve</tt> function (or <tt>reject</tt>). The special functions are provided to a callback that gets passed to the <tt>Promise</tt> constructor</p>
<code>
// the creator of the promise provides a function that handles the special resolve/reject functions
const getSomeNumber = new JonPromise(function(resolve, reject) {
setTimeout(() => {
resolve(Math.ceil(Math.random() * 10));
}, 1000); // <- happens 1 second in the future
// theres some weird inversion of control here make sure you understand it
});
getSomeNumber.then((value) => {
alert(`wow we got the number ${value}`)
});
</code>
<button>Run code</button>
<p>This definition of <tt>JonPromise</tt> is not fully functional...
CSS
code {
white-space: pre;
}
button {
display: block;
}
JavaScript
class JonPromise { // Vanilla JavaScript PogChamp
constructor(f) {
this.boundToThen = [];
this.boundToCatch = [];
const resolve = (someValue) => {
this.boundToThen.forEach(g => g(someValue));
};
const reject = (someError) => {
this.boundToCatch.forEach(h => h(someError) );
}
f(resolve, reject);
}
then(f) {
this.boundToThen.push(f);
}
catch(f) {
this.boundToCatch.push(f);
}
}
// magic run code block stuff
document.addEventListener('click', (e) => {
if (e.target.tagName !== 'BUTTON') {
return;
}
let p = e.target;
while (p.tagName !== 'CODE') {
p = p.previousSibling;
}
const code = p.innerText;
eval(code);
});