Promise系列学习
Promise
2.1 什么是Promise
2.1.2 promise的状态改变(promiseState)
-
pending变为resolved
-
pending变为rejected
-
说明:只有这2种,且一个promise对象只能改变一次
无论变为成功还是失败,都会有一个结果数据
成功的结果数据一般称为value,失败的结果数据一般称为reason
2.1.3 promise 对象的值 (promiseResult)
- 保存着对象 成功/失败 的结果
- 只能由 resolve 或 reject 来修改
2.1.4 promise 的基本流程
2.2 为什么使用Promise?
-
支持链式调用,可以解决回调地狱问题
-
回调地狱:回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件。
-
回调地狱的缺点:
–不便于阅读
–不便于异常处理
-
解决方案:
–使用promise链式调用
2.3 Promise的使用
-
封装异步操作
-
传递两个参数(回调函数):
–resolve:成功后执行,返回成功的结果
–reject:失败后执行,返回失败的结果
2.3.1 API
-
Promise的构造函数 Promise (executor){}
(1) executor 函数:执行器 ,含有两个形参 (resovle, reject) => {}
(2) resovle 函数:成功时的回调 value=>{}
(3) reject函数:失败时的回调 reason=>{}
注意:executor 函数是 同步调用的 executor 函数中的内容才是 异步调用的 -
Promise.prototype.then ()
-
Promise.prototype.catch ()
2.3.2 其他方法
-
Promise.all (promises)=>{}
–promises参数:包含n个promise的数组
–返回结果:返回一个新的promise,只有所有的promise都成功才成功,如果有一个失败,则返回失败。
–成功的返回值是一个有n个promise成功返回的结果组成的数组。
–失败的返回值是那个返回失败的promise返回的结果。
-
Promise.race(promises)=>{}
–promises参数:包含n个promise的数组
–返回一个新的promise,最终结果是 第一个执行完的promise的结果(谁快返回谁)。
2.3.3 如何改变 promise 的状态?
-
resovle():pending -> fulfilled (resovled)
-
reject():pending -> rejected
-
抛出错误: throw ‘xxx’
2.3.4 一个promise 指定多个成功/失败回调函数,都会调用吗?
当 promise 改变对应状态时(有执行上面说到的3种方法)都会调用。
const p = new Promise((resolve,rejected)=>{
resolve('hello promise!') // 改变状态
})
// 状态改变 => 两个回调都会执行
p.then((value)=>{
console.log('hello')
}
p.then((value)=>{
console.log('promise')
}
2.3.5 改变 promise 状态 和 指定回调函数 先后顺序?
当执行器里的任务是同步任务时:先改变状态
当执行器里的任务是异步任务时:先指定回调
2.3.6 如何中断 promise 链?
promise 状态改变才会执行回调,那么可以在要中断的地方返回一个pending状态的promise对象来中断 (这样状态一直为pending,并没有改变)。
p.then((value)=>{
console.log('hello')
}.then((value)=>{
console.log('promise')
return new Promise(()=>{}) // <==========
}.then((value)=>{
console.log('!')
}.then((value)=>{
console.log('?')
}.then((value)=>{
console.log('.')
}
2.4 Promise的调用=>then方法
-
有两个参数
promise.then((value)=>{ console.log('resolve'+value) },(reason)=>{ console.log('reject'+reason) })
-
then方法提供一个供自定义的回调函数,若传入非函数,则会忽略当前then方法。
-
回调函数中会把上一个then中返回的值当做参数值供当前then方法调用。
-
then方法执行完毕后需要返回一个新的值给下一个then调用(没有返回值默认使用undefined)。
-
每个then只可能使用前一个then的返回值。
2.5 封装ajax请求
2.5.1 FormData对象
-
用途
1.用一些键值对来模拟一系列表单控件:即把form中所有的元素的name与value组成一个queryString。
2.异步上传二进制文件。
-
使用
1.创建一个实例对象
let formData = new FormData console.log(formData)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qUQNLoKH-1663512471727)(C:\Users\susu\AppData\Roaming\Typora\typora-user-images\1663472095318.png)]
2.使用已有的表单来初始化一个对象实例
<form id="myForm" action="" method="post"> <input type="text" name="name">name <input type="password" name="psw">password <input type="submit" value="提交"> </form>
// 获取页面已有的一个form表单 let form = document.getElementById("myForm"); let formData = new FormData(form);
3.API
取值
formData.get("name"); // 获取key为name的第一个值 formData.getAll("name"); // 返回一个数组,获取key为name的所有值
添加数据
formData.append("k1", "v1"); formData.append("k1", "v2"); formData.append("k1", "v1");
删除数据
formData.delete("k1");
修改数据
formData.set("k1", "1");
判断key是否存在
formData.has("k1"); // true formData.has("k2"); // true formData.has("k3"); // false
遍历
每调用一次next()返回一条数据,数据的顺序由添加的顺序决定
返回的是一个对象,当其done属性为true时,说明已经遍历完所有的数据,这个也可以作为判断的依据
返回的对象的value属性以数组形式存储了一对key/value,数组下标0为key,下标1为value,如果一个key值对应多个value,会变成多对key/value返回。let i = formData.entries(); i.next(); // {done:false, value:["k1", "v1"]} i.next(); // {done:fase, value:["k1", "v2"]} i.next(); // {done:fase, value:["k2", "v1"]} i.next(); // {done:true, value:undefined}
2.5.2 XMLHttpRequest对象
-
如何使用
// 发送Ajax请求 function sendAjax() { //构造表单数据 var formData = new FormData(); formData.append('username', 'johndoe'); formData.append('id', 123456); //创建xhr对象 var xhr = new XMLHttpRequest(); //设置xhr请求的超时时间 xhr.timeout = 3000; //设置响应返回的数据格式 xhr.responseType = "text"; //创建一个 post 请求,采用异步 xhr.open('POST', '/server', true); //注册相关事件回调处理函数 xhr.onload = function(e) { if(this.status == 200||this.status == 304){ alert(this.responseText); } }; xhr.ontimeout = function(e) { ... }; xhr.onerror = function(e) { ... }; xhr.upload.onprogress = function(e) { ... }; //发送数据 xhr.send(formData); }
2.5.3 封装ajax请求
-
封装
const p = new Promise((resovle, reject) => { const xhr = new XMLHttpRequest() xhr.open('GET', 'https://api.apiopen.top/getJok') xhr.send() xhr.onreadystatechange = function() { if (xhr.status == 200) { resovle(xhr.response) } else { reject(xhr.status) } } })
-
调用
p.then(value => { console.log(value); }, reason => { console.log(reason) })
2.5.4 封装读取文件
-
封装
function myReadFile(path) { return new Promise((resolve, reject) => { require('fs').readFile(path, (err, data) => { if (err) reject(err) resolve(data) }) }) } myReadFile('/note.txt').then(value => { console.log(value); }, reason => { console.log(reason); })