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)