Tag: JavaScript
Write a MyPromise
class based on the native Promise
built-in class.
An instance of the MyPromise
class will always have one of three states: 'pending'
, 'fulfilled'
, or 'rejected'
. This state should be accessible through the state
getter method.
When a MyPromise
is in the fulfilled or rejected state, it will have a value which should be accessible through the value
getter method. A pending promise should always have the value of null
.
The MyPromise
constructor takes in an executor function, which takes two callbacks: resolve
and reject
. This executor function should run immediately. Both of the callbacks passed to the executor function take in a value, which when called will set the value of the MyPromise
as well as update the state based on which callback was called (resolve
sets it to fulfilled, while reject
sets it to rejected). If the executor function throws an error, the MyPromise
should be rejected with the error value. For simplicity, you can assume only one of these callbacks will ever be called, and it will never be called more than once.
An instance of the MyPromise
class should have two public methods: then
and catch
with the following functionality:
-
then(onFulfilled, onRejected)
: Runs one of the callbacks after theMyPromise
has settled. If theMyPromise
is fulfilled, the value should be passed to theonFulfilled
callback. If theMyPromise
is rejected, the value should be passed to theonRejected
callback. The then method should return a newMyPromise
that resolves to the value as returned by eitheronFulfilled
oronRejected
. If eitheronFulfilled
oronRejected
throws an error, the returnedMyPromise
should be rejected with that error value. -
catch(onRejected)
: Runs theonRejected
callback after theMyPromise
has been rejected. The value should be passed to theonRejected
callback. Thecatch
method should return a newMyPromise
that resolves to the value returned byonRejected
. IfonRejected
throws an error, the returnedMyPromise
should be rejected with that error value.
Both then
and catch
return new MyPromise
objects, meaning these methods should be chainable with the next call in the chain not running until the previous call completes. None of these callbacks should run until all other code in the call stack completes (i.e. they should be treated as microtasks by the event loop).
If multiple calls to then
and/or catch
are made on the same MyPromise
, their callback functions should be invoked in the order that then
and catch
were called (see sample usage #2).
All of the callback functions to then
and catch
are optional. If the required callback is not passed, a new MyPromise
should be returned with the previous value and state.
Your code should not use the native Promise
object in any way.
const promise = new MyPromise((res, rej) => {
res(10);
});
promise
.then((val) => {
console.log(val);
return val + 10;
})
.then((val) => {
console.log(val);
throw val + 10;
})
.then(
(val) => {
console.log(val);
return val + 10;
},
(error) => {
console.log('error: ' + error);
return error + 20;
},
)
.then((val) => {
console.log(val);
throw val + 10;
})
.catch((error) => {
console.log('error: ' + error);
return error + 10;
})
.then((val) => {
console.log(val);
});
console.log('end'); // this line runs before the then/catch chain.
// Console logs:
end;
10;
20;
error: 30;
50;
error: 60;
70;
const promise = new MyPromise((res, rej) => {
res(10);
});
promise.then((val) => {
console.log(val);
return val + 10;
});
promise.then((val) => {
console.log(val);
return val + 5;
});
console.log('end'); // this line runs before the then/catch chain.
// Console logs:
end;
20;
15;