一、promise 出现的原因
是为了解决回调地狱的问题;
二、promise 概述:
最先由CommonJS社区提出,在ES2015中被标准化,成为了语言规范
三、promise 状态:
1、pending:等到中
2、fulfilled :成功 —— onFulfilled
3、rejected:失败 —— onRejected
4、pending 结果 一旦确定,就不能从改变状态fulfilled /rejected
理解:
promise 是一个对象,用来表示一个异步任务,结束之后,是成功还是失败,就像是内部对外部一个承诺,这个承诺有个待定的状态(pending),等待的过程,就会有结果fulfilled(成功)或rejected(失败),对于这个结果也有相对应的反应onFulfilled/onRejected;对于这个结果,一旦出来之后,就不能在改变,只能成功或失败。
四、promise 用法
const promise = new Promise(function(resolv,reject){ //这里用于兑现承诺 ,只能是成功/失败,一旦这个承诺结果出来,就不能在改变 resolve(100) //承诺达成 // reject(new Error('promise reject')) //承诺失败})promise.then(function(val){ console.log('resolved',val);},function(val){ console.log('reject',val);});console.log('end') // 优先执行,再执行 promise 回调// 执行 resolve(100) 打印结果 resolved 100、// reject(new Error('promise reject')) 打印结果 错误
五、promise AJAX 案例
// 封装function ajax(url) { return new Promise(function(resolv,reject){ let xhr = new XMLHttpRequest(); xhr.open('GET',url); xhr.responseType = 'json' xhr.onload = function(){ if(this.status === 200){ resolve(this.response) }else{ reject(new Error(this.statusText)) } }; xhr.send(); })}//调用ajax('xxx').then(function(res){ console.log(res)},function(error){ console.log(error)})
六、promise 链式调用
var promise = ajax('xxx')var promise2 = promise.then(function onFulfilled(value){ console.log('onFulfilled',value)},function onRejected(error){ console.log('onRejected',error)})console.log(promise2) //Promise 对象console.log(promise2 === promise); //false
Promise 对象的 then 方法会返回一个全新的 Promise 对象
后面的 then 方法就是在为上一个 then 返回的 Promise 注册回调
前面的 then 方法中回调函数的返回值会作为后面 then 方法回调的参数
如果回调中返回的是 Promise , 那后面 then 方法的回调会等待它的结束
ajax('XXXX').then(funtion(val){ console.log('111'); return ajax('XXX')}).then(funtion(val){ // 这里是执行上个方法返回的回调 console.log('222'); console.log(val); // ajax('XXX') return ajax('XXX')}).then(funtion(val){ // 这里是执行上个方法返回的回调 console.log('222'); console.log(val); // ajax('XXX') return 'foo'}).then(funtion(val){ // 这里是执行上个方法返回的回调 console.log('222'); console.log(val); // foo return ajax('XXX')}).catch(err=>{ console.log(err); // foo})
七、promise 异常:
在代码中明确捕获每一个可能的异常
八、promise 静态
Promise.resolve('foo').then(value=>{ console.log(value);//foo})// 等同于 new Promise((resolve,reject)=>{ resolve('foo')}) // 等同于 Promise.resolve({ then:function(onFulfilled,onRejected){ onFulfilled('foo') }}).then(value=>{ console.log(value);//foo})
九、promise 并行执行
1、Promise.all
接收一个数组参数,数组里面全部都为 Promise 对象,在全部结束之后,将会触发 then ,当有一个失败, 会触发 catch
2、Promise.race
race 传入 Promise 数组,以第一个结束的为主,第一个结束后,就会中断(不论resolve/reject)
function ajax(url) { return new Promise(function(resolv,reject){ let xhr = new XMLHttpRequest(); xhr.open('GET',url); xhr.responseType = 'json' xhr.onload = function(){ if(this.status === 200){ resolve(this.response) }else{ reject(new Error(this.statusText)) } }; xhr.send(); })}// urls.json{ 'users': 'api/users.json' 'posts': 'api/posts.json'}// Promise.allajax('urls.json').then(value=>{ const urls = Object.values(value); const tasks = ursl.map(url=>ajax(urls)); return Promise.all}).then(values => { console.log(values); // api/users.json 和 api/posts.json里面的数据})// Promise.raceconst req = ajax('XXX.json')const timeout = new Promise ((resolve,reject)=>{ setTimeout(()=>{ // 这里是如果5秒之后还没执行成功 resolve,就会执行这里 reject(new Error('timeout'),500) })})Promise.race([req,timeout]).then(values => { console.log(values); }).catch(err=> { console.log(err); })
十、promise 执行时序/宏任务 vs 微任务
console.log('start');setTimeout(()=>{ console.log('setTimeout');},0)Promise.resolve().then(()=>{ console.log('Promise');}).then(()=>{ console.log('Promise1');})console.log('end');// 打印结果// 正常理解 start setTimeout Promise Promise1 end// 正确 start end Promise Promise1 setTimeout;这里涉及到宏任务、微任务
回调队列中的任务称之为【宏任务】,
宏任务:执行过程中可以临时加上一些额外需求,这个需求可以选择作为一个新的宏任务进到队列中排队。
微任务:也可以作为当前任务的微任务,微任务直接在当前任务结束过后立即执行。
promise 回调会作为微任务执行,所以自动直接执行。
而setTimeout 是作为宏任务,重新排队,所以最后执行。
十一、promise 处理异步最大的优势是,通过链式调用解决回调嵌套问题
(仅限个人学习笔记,如有不同见解,可以留言分享)