Promise
一、Promise
1、then()方法
(1)什么时候执行
pending->fulfilled时,执行then的第一个回调函数;
pending->rejected时,执行then的第二个回调函数;
(2)执行后的返回值
then方法执行后返回一个新的Promise对象;
(3)then方法返回的Promise对象的状态改变
在then的回调函数中,return后面的东西,会用Promise包装一下;
没有返回值的时候相当于return undefined;
return undefined ;等价于 return new Promise(resolve => {resolve(undefined)});
假如return 123;等价于 return new Promise(resolve => {resolve(123)});
默认返回的永远是成功的Promise对象。
2、catch()方法
catch 专门用来处理rejected状态;
catch本质上是then的特例;【 then(null, err => {}) 】
catch可以捕获它前面的错误;一般总是建议,Promise对象后面要跟catch方法,这样可以处理Promise内部发生的错误;
3、finally()方法(实际开发中并不常用)
当Promise状态发生变化时,不论如何变化都会执行,不变化不执行;
finally()本质也是then()的特例:
4、Promise.resolve()和Promise.reject()
(1)Promise.resolve()是成功状态Promise的一种简写形式;
当Promise.resolve()接收的是Promise对象时,直接返回这个Promise对象,什么都不做;console.log(Promise.resolve(p1) === p1); // true
当resolve函数接收的是Promise对象时,后面的then会根据传递的Promise对象的状态变化决定执行哪一个回调;
Promise.resolve(value)方法返回一个以给定值解析后的Promise 对象。
特殊情况2:如果参数是一个具有then方法的对象,Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。
(2)Promise.reject()是失败状态的一种简写形式;
不管什么参数,都会原封不动向后传递,作为后续方法的参数;
5、Promise.all()
Promise.all()关注多个Promise对象的状态变化;
传入多个Promise实例,包装成一个新的Promise实例返回;
Promise.all()的状态变化与所有传入的Promise实例对象状态有关,所有状态都变成resolved,最终的状态才会变成resolved;只要有一个变成rejected,最终的状态就变成rejected;
Promise.all()会返回一个Promise实例,这个实例对象的状态,要看Promise.all()的各个参数是否成功;
6、Promise.race() 和Promise.allSettled()
(1)Promise.race()的状态取决于第一个完成的Promise实例对象,如果第一个完成的成功了,那最终的就成功;如果第一个完成的失败了,那最终的就失败;
(2)Promise.allSettled()的状态与传入的Promise状态无关,永远都是成功的,它只会忠实的记录下各个Promise的表现;
7、Promise.any([])
(1)Promise.any()方法用于返回第一个成功的promise。只要有一个promise成功此方法就会终止,它不会等待其他的promise全部完成;
实际开发中,可能会有这样的需求:一次性加载多张图片,哪一张先加载出来就显示哪一张。那么此时就可以使用Promise.any()方法。
(2)传入的参数是一组Promise实例,那么所有Promise实例都变成rejected状态,返回的Promise才会变成rejected状态,参数中只要有一个Promise改变为成功状态,则返回的Promise状态就是成功的状态。
二、async/await
async/await方式使得异步操作变得更加方便和易读,它是基于Promise的;
以前的方法有回调函数和Promise,async/await是写异步代码的新方式;
async函数返回一个Promise对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句;
注意事项:
(1)await命令只能在async函数之中,如果用在普通函数,就会报错;
(2)await后面跟着一个Promise对象,会等待Promise返回结果,再继续执行后面的代码;
(3)await后面跟着的是一个数值或者字符串等数据类型的话,则直接返回该值;
(4)await后面跟着的是定时器,不会等待定时器里面的代码执行完,而是直接执行后面的代码,然后再执行定时器中的代码;
捕获错误:可以直接用标准的try/catch语法捕获错误;
三、Fetch API
Fetch API可以执行XMLHttpRequest对象的所有任务,更容易使用,接口也更现代化,Fetch API必须是异步;
3.1 基本用法:
fetch()方法是暴露在全局作用域中的,包括主页面执行线程、模块和工作线程。调用这个方法,浏览器就会定向给定URL发送请求。
(1)分派请求
fetch()只有一个必需的参数input。多数情况下,这个参数是要获取资源的url。这个方法返回一个期约。
请求完成、资源可用时,期约就会解决为一个Response对象。这个对象是API的封装,可以通过它取得相应的资源。
(2)读取响应
读取响应内容最简单的方式是取得纯文本格式的内容,这要用到text()方法。这个方法返回一个期约,会解决为取得资源的完整内容。(内容的结构通常是打平的)
(3)处理状态码和请求失败
Fetch API支持通过Response的status(状态码)和statusText(状态文本)属性检查响应状态。成功获取响应的请求通常会产生值为200的状态码。
只要服务器返回了响应,fetch()期约都会解决(尽管请求可能失败)。至于真正的“成功”请求,则需要在处理响应时再定义。
违反 CORS、无网络连接、HTTPS 错配及其他浏览器/网络策略问题都会导致期约被拒绝。可以通过 url 属性检查通过 fetch()发送请求时使用的完整 URL:
fetch(**'qux**').then((response) => console.log(response.url));
(4)自定义选项
只使用URL时,fetch()会发送GET请求,值包含最低限度的请求头。要进一步配置如何发送请求,需要传入可选的第二个参数init对象。
3.2 常见的Fetch请求模式
与XMLHttpRequest一样,fetch()既可以发送数据也可以接收数据。使用init对象参数,可以配置fetch()在请求体中发送各种序列化的数据。
(1)发送JSON数据
(2)在请求体中发送参数
(3)发送文件:因为请求体支持 FormData 实现,所以 fetch()也可以序列化并发送文件字段中的文件
(4)加载Blob文件
(5)发送跨源请求
从不同的源请求资源,响应要包含 CORS 头部才能保证浏览器收到响应。没有这些头部,跨源请求
会失败并抛出错误。
**跨源资源共享(CORS,Cross-Origin Resource Sharing)正式的跨域方案。**XHR 对象原生支持 CORS。图片探测和 JSONP 是另外两种跨域通信技术,但没有 CORS 可靠。还有使用代理服务器。
(6)中断请求
Fetch API 支持通过 AbortController/AbortSignal 对中断请求。调用 AbortController.
abort()会中断所有网络传输,特别适合希望停止传输大型负载的情况。中断进行中的 fetch()请求会
导致包含错误的拒绝。