回调与promise
回调
//回调: 用于请求数据。每次调用都传入一个回调函数 function hui(bb){ bb && bb(); //判断传进来的bb 是否存在,若存在是否函数,若函数就调用 } hui(function(){ console.log(1); hui(function(){ //这里面可以调用console.log(1)那一层的内容 console.log(2); hui(function(){//这里面可以调用console.log(2)那一层的内容 console.log(3); }); }); }); //这样嵌套地调用维护成本高,个人建议两层以上就不要用这种方法了,改用promise
Promise
//promise: 用于请求数据 function hui(){ return new Promise(bb => { bb(); }); } hui() .then(function(){ //每一个Promise都有一个then方法 console.log(1); return hui(); //若下面还有用到then,必须返回Promise实例,而Promise实例就在hui()中 }) .then(function(){ //then里面的function对应的是,hui()里面的bb console.log(2); return hui(); }) .then(function(){ console.log(3); //下面没有then了,就不必返回Promise实例 })
信任问题
//一般回调 //如调用第三方库,并传入一个回调 function methods(cb){ //未按照所想预期执行回调 setTimeout(function(){ //现在执行一下回调 cb&&cb(); //不明情况下又执行了一下回调,最后导致程序出错 cb&&cb(); },2000) }
//Promise //Promise一旦确认为成功或失败 就不能被更改 function methods(){ return new Promise(resolve => { setTimeout(function(){ resolve(); //成功一次只能调用一次Promise里面的回调 resolve(); //第二次调用是不会成功的 },2000) }) }
错误处理
//promise有成功也有失败。
失败的回调(不传参)
//不传参 //promise失败的情况下的处理 function methods(val){ return new Promise((resolve,reject) => { if(val){ //若val为true,则执行成功做的事 resolve(); }else{ //若val为false,则执行失败做的事 reject(); } }); } //then(resolve,reject) //then方法中,第二个回调是失败时做的事 methods(false) .then(()=>{ console.log('成功'); },()=>{ console.log('失败'); })
失败的回调(传参)
//传参 //promise失败的情况下的处理 function methods(val){ return new Promise((resolve,reject) => { if(val){ resolve({name:'萱萱',age:18}); //成功时传入的参数,只能传一个参数。若传的是对象,里面可包含多个数据 }else{ reject('404'); //失败时传入的参数。同样只能传一个参数 } }); } methods(false) .then(success=>{ console.log(success); //成功时接收的参数 },fail=>{ console.log(fail);//失败时接收的参数 })
catch
//捕获错误,并对其进行处理
//catch //使用catch的实例方法,可以捕获错误 methods(true) .then(()=>{ console.log('先成功后失败'); return methods(false); //若返回了false,后面没有与之对应的回调或catch就会出错 }) .then(()=>{ console.log('第一个回调是成功执行的,所以这条语句会被跳过'); }) // //方法一 // .then(()=>{ //成功的回调 // console.log('这里的成功回调也不会被执行'); // },()=>{ //失败的回调 // console.log('若前面的错误回调一直没有被执行,那么就会延续到这里执行') // }) //方法二 .catch(()=>{ console.log('这条是用来捕获错误用的'); })
finally
//最后执行的内容
//finally //无论成功或失败都会执行finally .finally(()=>{ console.log('最后才会执行的内容'); })
promise的三种状态
//状态的改变不可逆,一旦决议就不能再修改
pending: 进行中
fulfilled:成功
rejected:失败
//一旦从pending变成了fulfilled,或从pending变成了rejected,就不能够更改了
Promise.all
//将多个promise实例,包装成一个新的promise实例。
即 Promise.all ([ promise1 , promise2 ] )
1、当promise里面全部决议为成功,promise.all才会决议为成功,并将resolve所带的参数,按顺序组成一个数组返回
2、当promise里面有一个决议为失败,promise.all就会决议为失败,并将决议失败的rejected所带的参数,按顺序组成一个数组返回
3、当 Promise.all 为空数组的时候,就会决议为成功,即 Promisse.all ([ ])
// Promise.all function getData1(val){ return new Promise((resolve,reject)=>{ if (val) { resolve('data1'); }else{ reject('data1 error') } }) } function getData2(val){ return new Promise((resolve,reject)=>{ if (val) { resolve('data2'); }else{ reject('data2 error') } }) } function getData3(val){ return new Promise((resolve,reject)=>{ if (val) { resolve('data3'); }else{ reject('data3 error') } }) } let p = Promise.all([getData1(true),getData2(true),getData3(true)]); p.then(arr=>{ console.log('当所有promise实例决议为true时,才输出') console.log(arr); },e=>{ console.log('当某一项为false时,输出某一项的reject信息'); console.log('若有两项错误信息,则输出最先出现的那个错误信息'); console.log(e); })
//当promise.all里为空数组时,决议为true let p = Promise.all([]); p.then(arr=>{ console.log('当promise.all里为空数组时,决议为true') console.log(arr); },e=>{ console.log(e); })
Promise.race
//在promise的实例中,只要有一个返回成功/失败,那么promise.race就为成功/失败
//若promise.race接收的是空数组,则会永远地挂起
//Promise.race //在promise的实例中,只要有一个返回成功/失败,那么promise.race就为成功/失败 const promise1 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, 'one'); }); const promise2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, 'two'); }); Promise.race([promise1, promise2]).then(function(value) { console.log(value); // 两个都是成功的,但是promise2反应速度更快,所以这里的就是two }); // expected output: "two"
Promise.resolve() 与 Promise.reject()
//常用来生成已经被决议为成功或失败的Promise实例
Promise.resolve()传递参数时,有3种情况
第一种,传递普通值
let p1 = new Promise(resolve=>{ //两条语句的效果都一模一样 resolve('成功'); }); let p2 = Promise.resolve('成功'); //两条语句的效果都一模一样
第二种,传递promise实例
let p = new Promise(resolve=>{ resolve('好'); }) let pp = Promise.resolve(p); //直接将p的promise实例返回给pp,即 p === pp pp.then(data=>void console.log(data)); //这里接收的参数是p里面resolve的参数
第三种,传递一个thenable对象
//thenable就是具有then方法的对象 let obj = { then(cb){ console.log('obj里面的then被执行了'); cb('这里相当于resolve传递参数'); }, oth(){ console.log('其他'); } }; //立即执行then方法 Promise.resolve(obj).then(data =>{ console.log(data); });
//不管什么值,只要Promise.resolve包一下就成为了promise实例了。
Promise.reject()
//只要决议为失败,会按照原来的原封不动地传递过来
Promise.reject({then() {console.log('并不会解析这条内容,只负责传递');} }) .then(()=>{ //这里是决议成功的函数,这里用不到 },e=>{ console.log(e); //这里输出的是then函数本身,不会进行解析 });
Promise同步与异步
//promise决议之后,异步地执行后面地事情,异步任务在同步任务之后执行。如then里面就是异步任务。
根据这个特性,可将同步任务转为异步任务
function createAsyncTask(syncTack){ return Promise.resolve(syncTack).then(syncTack=>{ syncTack() }); } createAsyncTask(()=>{ console.log('我变成了异步任务'); return 1+1; }).then(res=>{ console.log(res); }); console.log('我是同步任务');