这 10 个片段,有助于你理解 ES 中的 Promise
在开发中,了解 JavaScript 和 Promise 基础,有助于提高我们的编码技能,今天,我们一起来看看下面的 10 片段,相信看完这 10 个片段有助于我们对 Promise 的理解。
片段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
// thirdPromise同步执行,promise.then异步执行。
片段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"
// 2 秒后还会在打一遍上面的两个
promise 有三种不同的状态:
- pending
- fulfilled
- rejected
一旦状态更新,pending->fulfilled 或pending->rejected,就可以再次更改它。 prom1与prom2不同,并且两者都返回新的Promise状态。
片段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即使reject后有一个resolve调用,也只能执行一次resolve或reject ,剩下的不会执行。
片段 4:
Promise.resolve(1)
.then(res => {
console.log(res);
return 2;
})
.catch(err => {
return 3;
})
.then(res => {
console.log(res);
});
// 1
// 2Promises 可以链接调用,当提到链接调用 时,我们通常会考虑要返回 this,但Promises不用。 每次 promise 调用.then或.catch时,默认都会返回一个新的 promise,从而实现链接调用。
片段 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 fourthpromise 的 .then或.catch可以被多次调用,但是此处Promise构造函数仅执行一次。 换句话说,一旦promise的内部状态发生变化并获得了一个值,则随后对.then或.catch的每次调用都将直接获取该值。
片段 6:
const promise = Promise.resolve()
.then(() => {
return promise
})
promise.catch(promise )
// [TypeError: Chaining cycle detected for promise #<Promise>]
// Uncaught SyntaxError: Identifier 'promise' has already been declared
// at <anonymous>:1:1
// (anonymous) @ VM218:1.then或.catch返回的值不能是promise本身,否则将导致无限循环。
片段 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 ...在.then或.catch中返回错误对象不会引发错误,因此后续的.catch不会捕获该错误对象,需要更改为以下对象之一:
return Promise.reject(new Error('error')) throw new Error('error')
因为返回任何非promise 值都将包装到一个Promise对象中,也就是说,返回new Error('error')等同于返回Promise.resolve(new Error('error'))。
片段 8:
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
// 1.then或.catch的参数应为函数,而传递非函数将导致值的结果被忽略,例如.then(2)或.then(Promise.resolve(3)。
片段 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可以接受两个参数,第一个是处理成功的函数,第二个是处理错误的函数。 .catch是编写.then的第二个参数的便捷方法,但是在使用中要注意一点:.then第二个错误处理函数无法捕获第一个成功函数和后续函数抛出的错误。 .catch捕获先前的错误。 当然,如果要重写,下面的代码可以起作用:
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)
})片段 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
process.nextTick和promise.then都属于微任务,而setImmediate属于宏任务,它在事件循环的检查阶段执行。 在事件循环的每个阶段(宏任务)之间执行微任务,并且事件循环的开始执行一次。
原文:http://jamesknelson.com/
作者:Jay Chow
译者:前端小智
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!