There are many great ways to improve your coding skills, experiment with new technologies. The truth of the matter is to understand JavaScript and Promise.
Part 1:
const prom = new Promise((res, rej) => { console.log('first'); res(); console.log('second'); }); prom.then(() => { console.log('third'); }); console.log('fourth'); // first // second // fourth // third
Promise
executes synchronously, promise.then
executes asynchronously
Part 2:
const prom = new Promise((res, rej) => { setTimeout(() => { res('success'); }, 1000); }); const prom2 = prom.then(() => { throw new Error('error'); }); console.log('prom', prom); console.log('prom2', prom2); setTimeout(() => { console.log('prom', prom); console.log('prom2', prom2); }, 2000); // prom // Promise {<pending>} // __proto__: Promise // [[PromiseStatus]]: "resolved" // [[PromiseValue]]: "success" // prom2 // Promise {<pending>}__proto__: // Promise[[PromiseStatus]]: "rejected"[[PromiseValue]]: // Error: error // at <anonymous>:7:9
promise
has three different states:
- pending
- fulfilled
- rejected
Once the status updated, pending->fulfilled
or pending->rejected
, it can be changed again. The prom1
is different from prom2
and both of them return new Promise status.
Part 3:
const prom = new Promise((res, rej) => { res('1'); rej('error'); res('2'); }); prom .then(res => { console.log('then: ', res); }) .catch(err => { console.log('catch: ', err); }); // then: 1
The resolve
or reject
only execute once even there is a resolve call after the reject. It won't execute.
Part 4:
Promise.resolve(1) .then(res => { console.log(res); return 2; }) .catch(err => { return 3; }) .then(res => { console.log(res); }); // 1 // 2
Promises can be chained. When referring to chained calls, we usually think of returning this, but Promises do not. Each time a promise calls .then
or .catch
, a new promise will be returned, thus implementing chained calls.
Part 5:
const promise = new Promise((resolve, reject) => { setTimeout(() => { console.log('first') resolve('second') }, 1000) }) const start = Date.now() promise.then((res) => { console.log(res, Date.now() - start, "third") }) promise.then((res) => { console.log(res, Date.now() - start, "fourth") }) // first // second 1054 third // second 1054 fourth
A promise .then
or .catch
can be called multiple times, but here the Promise constructor is executed only once. In other words, once the internal state of a promise changes and a value is obtained, each subsequent call to .then
or .catch
will directly get the value.
Part 6:
const promise = Promise.resolve() .then(() => { return promise }) promise.catch(console.error) // [TypeError: Chaining cycle detected for promise #<Promise>] // Uncaught SyntaxError: Identifier 'promise' has already been declared // at <anonymous>:1:1 // (anonymous) @ VM218:1
The value returned by .then
or .catch
cannot be the promise itself, otherwise, it will cause an infinite loop.
Part 7:
Promise.resolve() .then(() => { return new Error('error'); }) .then(res => { console.log('then: ', res); }) .catch(err => { console.log('catch: ', err); }); // then: Error: error! // at Promise.resolve.then (...) // at ...
Returning an error object in .then
or .catch
does not throw an error, so it will not be caught by subsequent .catch
, you need to change to one of them:
return Promise.reject(new Error('error')) throw new Error('error')
Because returning any non-promise value will be wrapped into a promise object, that is, return new Error ('error') is equivalent to return Promise.resolve (new Error ('error')).
Part 8:
Promise.resolve(1) .then(2) .then(Promise.resolve(3)) .then(console.log) // 1
The argument of .then or .catch is expected to be a function, and passing in a non-function will results the result of value to be ignored such as .then(2)
or .then(Promise.resolve(3)
.
Part 9:
Promise.resolve() .then( function success(res) { throw new Error('Error after success'); }, function fail1(e) { console.error('fail1: ', e); } ) .catch(function fail2(e) { console.error('fail2: ', e); }); // fail2: Error: Error after success // at success (<anonymous>:4:13)
.then
can accept two parameters, the first is a function that handles success, and the second is a function that handles errors. .catch
is a convenient way to write the second parameter of .then
, but there is one thing to pay attention to in usage: .then
the second error-handling function cannot catch the error thrown by the first successful function and subsequent ones. catch catches previous errors. Of course, the following code works if you want to rewrite:
Promise.resolve() .then(function success1 (res) { throw new Error('success1 error') }, function fail1 (e) { console.error('fail1: ', e) }) .then(function success2 (res) { }, function fail2 (e) { console.error('fail2: ', e) })
Part 10:
process.nextTick(() => { console.log('1') }) Promise.resolve() .then(() => { console.log('2') }) setImmediate(() => { console.log('3') }) console.log('4'); // Print 4 // Print 1 // Print 2 // Print 3
Both process.nextTick
and promise.then
belong to microtask, while setImmediate
belongs to macrotask, which is executed during the check phase of the event loop. A microtask is executed between each phase of the event loop (macrotask), and the beginning of the event loop is executed once.
Top comments (0)