当前位置: 首页 > Web前端 > HTML

【面试题目】JS异步Promise,Generator,Async

时间:2023-04-02 14:54:37 HTML

JS异步Promise,Generator,AsyncPromise解决的问题:回调地狱Promise规范:Promise有三种状态,waiting(待定),completed(fulfilled/resolved),Rejected。Promise的状态只能从“waiting”变为“completed”或“rejected”。不可逆转,“完成”和“拒绝”不能相互转换。Promise必须提供一个then方法来访问它的当前值、未来值和原因。promise.then(resolve,reject),resolve和reject是可选参数。如果resolve或reject不是函数,则必须忽略它。then方法必须返回一个promise对象。使用:promise对象的实例化需要传入一个函数(包含两个参数),resolve和reject,内部判断状态。resolve和reject函数可以在回调函数中使用传入的参数。resolve和reject都是函数,在then的回调函数中接收传入的参数。varpromise=newPromise(function(resolve,reject){setTimeout(function(){resolve('哈哈哈哈');});});promise.then(function(val){console.log(val)})then接收两个函数,分别对应resolve和reject状态的回调,函数中接收实例化时传入的参数.promise.then(val=>{//resolved},reason=>{//rejected})catch相当于.then(null,rejection)当没有传入rejectionthen时,错误会冒泡进入catch函数,如果传入rejection,则错误会被rejection捕获,不会进入catch。另外then中回调函数发生的错误只会在下一层then中被捕获,不会影响promise的状态。newPromise((resolve,reject)=>{thrownewError('error')}).then(null,(err)=>{console.log(err,1);//在此处捕获}).catch((err)=>{console.log(err,2);});//比较newPromise((resolve,reject)=>{thrownewError('error')}).then(null,null).catch((err)=>{console.log(err,2);//抓住这里});//错误示例newPromise((resolve,reject)=>{resolve('普通的');}).then((val)=>{thrownewError('回调函数出错')},(err)=>{console.log(err,1);}).then(null,(err)=>{console.log(err,2);//这里捕获,也可以用catch});两者不等价的情况:此时catch抓到的不是p1的错误,而是p2的错误,p1().then(res=>{returnp2()//p2返回一个promise对象}).catch(err=>console.log(err))错误捕获的错误案例:在这个函数调用中即使发生错误,仍然会在then中进入resolve回调函数,因为catch在promise的时候已经被调用了object是在函数p1中实例化的,如果出错就会进入catch,此时会返回一个新的promise,所以即使出错了还是会进入then链中的resolve回调函数p1函数。functionp1(val){returnnewPromise((resolve,reject)=>{if(val){varlen=val.length;//传入null会发生错误,进入catch捕获错误resolve(len);}else{reject();}}).catch((err)=>{console.log(err)})};p1(null).then((len)=>{console.log(len,'resolved');},()=>{console.log('rejected');}).catch((err)=>{console.log(err,'catch');})Promise回调链:promise可以在回调函数中使用return和throw,所以在then中,你可以返回一个promise对象或其他值,或者抛出一个错误对象,但是如果没有返回,则默认返回undefineded,那么then中接收到的回调参数将是未定义的。functionp1(val){returnnewPromise((resolve,reject)=>{val==1?resolve(1):reject()})};functionp2(val){returnnewPromise((resolve,reject)=>{val==2?resolve(2):reject();})};letpromise=newPromise(function(resolve,reject){resolve(1)}).then(function(data1){returnp1(data1)//如果去掉return,会返回undefined,而不是p1的返回值,会报错}).then(function(data2){returnp2(data2+1)}).then(res=>console.log(res))Generator函数:Generator函数使用:1.分段执行,可以暂停2.可以控制阶段和每个阶段的返回值3.可以知道是否执行到结束function*g(){varo=1;产量o++;yieldo++;}vargen=g();console.log(gen.next());//对象{value:1,done:false}varxxx=g();console.log(gen.next());//对象{value:2,done:false}console.log(xxx.next());//对象{value:1,done:false}console.log(gen.next());//对象{value:undefined,done:true}generator和异步控制:利用Generator函数的暂停执行效果,可以在yield中写异步操作d语句中,等到next方法调用后再执行,其实就相当于不写回调函数,因为异步操作的后续操作可以放在yield语句下面,反正不会执行直到下一个方法被调用。因此,Generator函数一个重要的实际意义就是处理异步操作和重写回调函数。async与异步:用法:async表示这是一个async函数,await只能在这个函数中使用。await表示等待异步操作的结果返回后再继续。await之后通常是一个promise对象例子:async用于定义一个返回Promise的异步函数。如果async函数返回一个同步值,该值将被包装到一个理解resolve的Promise中,相当于returnPromise.resolve(value)。await在异步操作之前使用,用于“等待”异步操作的返回值。await也可以用于同步值。lettimer=asyncfunctiontimer(){returnnewPromise((resolve,reject)=>{setTimeout(()=>{resolve('500');},500);});}timer().then(result=>{console.log(result);//500}).catch(err=>{console.log(err.message);});//返回一个同步值letsayHi=asyncfunctionsayHi(){lethi=await'helloworld';回嗨;//相当于返回Promise.resolve(hi);}sayHi().then(result=>{console.log(result);});参考:PromiseMinibookpromisenotes手写promisepromise实现