以前总是似懂非懂,这次总算把它弄了个清楚
Promise
对象代表一个异步操作,有三种状态:pending
(进行中)、resolved
(已成功)和rejected
(已失败)Promise
对象的状态改变,只有两种可能:从pending
变为resolved
和从pending
变为rejected
Promise
。一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise
内部抛出的错误,不会反应到外部。第三,当处于pending
状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)创造Promise
实例时,必须传入一个函数作为参数
new Promise(() => {});
new Promise(); // 报错
该函数可以接收另外两个由JavaScript引擎提供的函数,resolve
和reject
。函数作用:
resolve
——将Promise
对象的状态从pending
变为resolved
,将异步操作的结果,作为参数传递出去reject
——将Promise
对象的状态从pending
变为rejected
,将异步操作报出的错误,作为参数传递出去let promise = new Promise((resolve, reject) => {
// do something
if (true) {
// 将参数返回,供then方法使用
resolve("value");
} else {
// 将参数返回,供then方法使用
reject("error");
}
});
Promise
实例生成以后,可以用then
方法分别指定resolved
状态和rejected
状态的回调函数。
promise.then(
value => {
// resolved时调用,value为resolve函数返回的参数
console.log(value);
},
err => {
// rejected时调用,err为reject函数返回的参数
console.log(err);
}
);
当then
方法只有一个函数参数时,此时为resolved
状态的回调方法
promise.then(value => {
// 只有状态为resolved时才能调用,如果返回的是rejected状态,则报错 Uncaught (in promise) error
console.log(value);
});
只有当promise的状态变为resolved或者rejected时,then方法才会被调用
Promise 新建后就会立即执行,并且调用resolve
或reject
后不会终结 Promise
的参数函数的执行。
let promise = new Promise(function(resolve) {
console.log("Promise");
resolve();
console.log("!!!")
});
promise.then(function() {
console.log("resolved.");
});
console.log("Hi!");
// Promise
// !!!
// Hi!
// resolved
resolve
返回的是另外一个Promise
实例const p1 = new Promise((_, reject) => {
setTimeout(() => reject('error'), 3000);
});
const p2 = new Promise(resolve => {
setTimeout(() => resolve(p1), 1000);
});
p2.then(
result => console.log(result),
error => console.log(error) // error
);
上面代码中,
p1
是一个Promise
,3 秒之后变为rejected
。p2
的状态在 1 秒之后改变,resolve
方法返回的是p1
。由于p2
返回的是另一个 Promise,导致p2
自己的状态无效了,由p1
的状态决定p2
的状态。所以,后面的then
语句都变成针对后者(p1
)。又过了 2 秒,p1
变为rejected
,导致触发catch
方法指定的回调函数。
以上是原文解释,我们可以理解成p2.then
实际上是p1.then
then
方法是定义在原型对象Promise.prototype
上的,同时then方法的两个参数都是非必选的。因为then方法返回的是一个**全新**
的promise实例时,因此then方法可以链式调用 then
方法在以下情况返回的promise
1 .
当未传入参数时,then方法会返回一个新的,状态和原promise相同的promise
const promise = new Promise(resolve => {
resolve("resolve");
});
let p = promise.then();
console.log(promise);
console.log(p);
结果展示
2 .
上一个promise未被成功调用then方法时,返回的结果如情形1
const promise = new Promise((_, reject) => {
reject("reject");
});
let a = promise.then(value => {
console.log(value);
});
3 .
上一个promise被成功调用then方法时,返回一个`resolve(undefined)`的promise
const promise = new Promise((_, reject) => {
reject("reject");
});
let a = promise.then(undefined, value => {
console.log(value);
});
console.log(a);
4 .
上一个promise被成功调用then方法,但出现报错,返回一个`reject('error')`的promise,`error`代指错误,并非真正的`reject`返回的结果
const promise = new Promise(resolve => {
resolve("resolve");
});
let p = promise.then(value => {
console.log(value);
throw new Error("fail1");
});
console.log(p);
结果展示:
5 .
给then方法手动返回一个promise,此时会覆盖掉默认的行为,返回值为新增的promise
const promise = new Promise(resolve => {
resolve("resolve");
});
let p = promise.then(
() =>
new Promise(resolve => {
resolve("resolve2");
})
);
console.log(p);
catch()
方法是.then(null, rejection)
或.then(undefined, rejection)
的别名,用于指定发生错误时的回调函数。
const promise = new Promise((_, reject) => {
reject("reject");
});
promise
.then(value => {
console.log(value);
})
// 发生错误,或者reject时执行
.catch(value => {
console.log(value);
});
如果 Promise 状态已经变成resolved
,再抛出错误是无效的。
const promise = new Promise(resolve => {
resolve("resolve");
throw new Error("fail");
});
promise.then(value => console.log(value));
promise中所有没有被处理的错误都会冒泡到最后一个catch中
const promise = new Promise(resolve => {
resolve("resolve");
});
promise
.then(value => {
console.log(value);
throw new Error("fail1");
})
.then(() => {
throw new Error("fail2");
})
.catch(value => {
console.log(value);
});
在上面的代码中,catch会优先打印打印第一个错误,当第一个错误解决之后(注释掉就ok),catch里才会打印第二个错误 catch的返回值仍是promise,返回promise的方式和then相似,因此,catch后仍然可以调用then方法
finally()
方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。finally
方法的回调函数不接受任何参数,这表明,finally
方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。
const promise = new Promise(resolve => {
resolve("resolve");
});
promise
.then(value => {
console.log(value);
throw new Error("fail1");
})
.then(() => {
throw new Error("fail2");
})
.catch(value => {
console.log(value);
});
finally
的本质
promise.finally(() => {
// do something
});
// 等同于
promise.then(
result => {
// do something
return result;
},
error => {
// do something
throw error;
}
);
finally
的返回值为一个新的和原来的值相似的promise
有时需要将现有对象转为 Promise 对象,Promise.resolve()
方法就起到这个作用,且实例状态为resolve
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
Promise.resolve()
方法的参数分成四种情况
const promise = new Promise(resolve => {
resolve("resolve");
});
let p = Promise.resolve(promise);
console.log(p == promise); // true
thenable
对象thenable
对象指的是具有then
方法的对象,Promise.resolve()
方法会将这个对象转为 Promise 对象,然后就立即执行thenable
对象的then()
方法
// thenable对象
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function (value) {
console.log(value); // 42
});
上面代码中,thenable
对象的then()
方法执行后,对象p1
的状态就变为resolved
,从而立即执行最后那个then()
方法指定的回调函数,输出42
then()
方法的对象,或根本就不是对象const p = Promise.resolve('Hello');
p.then(function (s) {
console.log(s) // Hello
});
Promise.resolve()
方法允许调用时不带参数,直接返回一个resolved
状态的 Promise 对象
Promise.resolve();
// 相当于
new Promise(resolve => resolve(undefined))
Promise.reject(reason)
方法也会返回一个新的 Promise 实例,该实例的状态为rejected
const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))
Promise.all()
方法用于将多个 Promise 实例,包装成一个新的 Promise 实例
const p = Promise.all([p1, p2, p3]);
面代码中,Promise.all()
方法接受一个数组作为参数,p1
、p2
、p3
都是 Promise 实例,如果不是,就会调用Promise.resolve
方法,将参数转为 Promise 实例,再进一步处理。另外,Promise.all()
方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。p
的状态由p1
、p2
、p3
决定,分成两种情况。
p1
、p2
、p3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时p1
、p2
、p3
的返回值组成一个数组,传递给p
的回调函数。p1
、p2
、p3
之中有一个被rejected
,p
的状态就变成rejected
,此时第一个被reject
的实例的返回值,会传递给p
的回调函数。let promise = Promise.all([1, 2, 3]);
promise.then(value => {
console.log(value); // [1,2,3]
});
console.log(promise);
情形一promise结果:
let p2 = Promise.reject(2);
let promise = Promise.all([1, p2, 3]);
promise
.then(value => {
console.log(value);
})
.catch(err => {
console.log(err); // 2
});
console.log(promise);
情形二promise结果:
如果作为参数的 Promise 实例,自己定义了catch
方法,那么它一旦被rejected
,并不会触发Promise.all()
的catch
方法
const p1 = new Promise(resolve => {
resolve("hello");
})
.then(result => result)
.catch(e => e);
const p2 = new Promise(() => {
throw new Error("报错了");
})
.then(result => result)
.catch(e => e); // p2实际上是catch返回的promise实例
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
Promise.race()
方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。Promise.race()
方法的参数与Promise.all()
方法一样,如果不是 Promise 实例,就会先调用下面讲到的Promise.resolve()
方法,将参数转为 Promise 实例,再进一步处理。
const p = Promise.race([p1, p2, p3]);
上面代码中,只要p1
、p2
、p3
之中有一个实例率先改变状态,p
的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p
的回调函数。
Promise.allSettled()
方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是fulfilled
还是rejected
,包装实例才会结束,参数与Promise.all()
方法一样
let p2 = Promise.reject(2);
let promise = Promise.allSettled([1, p2, 3]);
promise.then(value => {
console.log(value); // [{status: "fulfilled", value: 1},{status: "rejected", reason: 2},{status: "fulfilled", value: 3}]
});
console.log(promise);
Promise.allSettled()
的返回的promise实例状态只可能变成resolved
,它的监听函数收到的参数是一个数组,该数组的每个成员都是一个对象,每一个对象都有status属性,该属性的值只可能是字符串fulfilled
或字符串rejected
。fulfilled
时,对象有value
属性,rejected
时有reason
属性,对应两种状态的返回值。
该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。只要参数实例有一个变成fulfilled
状态,包装实例就会变成fulfilled
状态;如果所有参数实例都变成rejected
状态,包装实例就会变成rejected
状态。Promise.any()
跟Promise.race()
方法很像,只有一点不同,就是不会因为某个 Promise 变成rejected
状态而结束。
let p1 = Promise.reject(1);
let p2 = Promise.reject(2);
let promise = Promise.any([p1, p2, 3]);
promise.then(value => {
console.log(value); // 3
});
console.log(promise);
当所有的实例返回的状态都是rejected
时,Promise.any()
会返回一个的实例状态才为rejected
let p1 = Promise.reject(1);
let p2 = Promise.reject(2);
let promise = Promise.any([p1, p2]);
promise
.then(value => {
console.log(value);
})
.catch(value => {
console.log(value); // AggregateError: All promises were rejected
});
console.log(promise);
实际开发中,经常遇到一种情况:不知道或者不想区分,函数f
是同步函数还是异步操作,但是想用 Promise 来处理它。因为这样就可以不管f
是否包含异步操作,都用then
方法指定下一步流程,用catch
方法处理f
抛出的错误。一般就会采用下面的写法。
const f = () => console.log('now');
Promise.resolve().then(f);
console.log('next');
// next
// now
上面的写法有一个缺点,就是如果f
是同步函数,那么它会在本轮事件循环的末尾执行。鉴于这是一个很常见的需求,所以现在有一个提案,提供Promise.try
方法替代上面的写法。
const f = () => console.log('now');
Promise.try(f);
console.log('next');
// now
// next
带你写出符合 Promise/A+ 规范 Promise 的源码
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/wTFx3BsJ0UYnFYoD8rejFw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。