Promise相关
Promise相关
关于异步:
出现背景:
由于JS是单线程语言,因此所有网络操作、浏览器事件都必须是异步执行的。
异步解决方案:
方案一:回调函数方式(注册-执行异步任务-触发回调函数)
原理:
浏览器解释执行js代码过程中,遇到异步任务,首先在系统中挂起(异步队列中注册回调函数),当异步任务(eg:I/O,网络请求等操作完成之后),通过触发回调函数的方式完成整个异步操作。
异步的问题:
- 传统采用回调函数处理异步任务的方式可以处理问题,但可能进入回调地狱,剥夺return的权利
回调方式,代码嵌套层次深,易读性差,且不易维护
场景:
- setTimeOut
ajax请求
方案二:Promise方式
概念:
- Promise是一个对象:承诺将来会执行的对象(代表异步操作最终成功或者失败)
- promise作为队列最为重要的特性,我们在任何一个地方生成了一个promise队列之后,我们可以把他作为一个变量传递到其他地方。
- 三种状态:pending、fulfilled、rejected
- 两类函数:resolve(),将pending状态变为fulfilled状态,rejecte(),将pending状态变为rejected状态
thenable对象:具有特定格式then属性的对象
约定(与传统回调函数不同):
- 本轮Event Loop完成之前,回调函数不会被调用
- then函数总会被调用,即使它是异步操作完成之后才添加的
- 多次调用then,可以添加多个回调函数,它们会按照插入顺序,一个接一个独立执行
** 因此,Promise最直接的好处是链式调用
问题场景:
then方法中返回的不是Promise对象
- 若返回为空,程序默认返回值为null
- 若返回其他非Promise对象,程序直接进入下一级then方法中
catch + then
- catch只抓当前作用域的错误,过期不候
- catch之后还可以继续执行then方法,但是跳过的方法将不再执行
- 建议使用reject的方式抛出错误,而非new Error
console.log('程序开始执行') new Promise((resolve)=>{ setTimeout(()=>{ resolve() },200) }) .then(()=>{ console.log('then_1开始执行') reject('then_1中执行了reject方法') }) .then(()=>{ console.log('then_2开始执行') }) .catch((err)=>{ console.log('I catch' + err) }) .then(()=>{ console.log('then_3开始执行') }) .catch((err)=>{ console.log('最终err未执行') }) 输出结果: 程序开始执行 then_1开始执行 I catch then_1中执行了reject方法 then_3开始执行
方法:
// 包装不支持Promise语法的函数 new Promise() // 所有Promise任务执行完成才能执行then // Promise对象组成的数组作为参数 Promise.all() // 只要有其中一项完成,即可执行then Promise.race() // 手动创建一个resolve的Promise Promise.resolve() // 手动创建一个reject的Promise Promise.reject() Promise.prototype.then() Promise.prototype.catch() Promise.prototype.finally()
源码实现方式:
const PENDING = 'pending'; //初始状态 const FULFILLED = 'fulfilled'; // 成功状态 const REJECTED = 'rejected'; // 成功 function Promise(extutor){ let self = this; self.status = PENDING; // 设置状态 // 存放成功回调的数组 self.onResolveCallbacks = []; // 存放失败回调的数组 self.onRejectedCallbacks = []; function resolve(value){ if(self.status === PENDING){ self.status = FULFILLED; self.value = value; self.onResolveCallbacks.forEach(cb => cd(self.value)) } } function reject(reason){ if(self.status === PENDING){ self.status = REJECTED; self.value = reason; self.onRejectCallbacks.forEach(cb => cd(self.value)) } } try{ excutor(resolve, reject) } catch(e) { reject(e) } }
相关推荐
88254251 2020-11-01
bowean 2020-07-08
88520191 2020-07-05
Magicsoftware 2020-06-11
whynotgonow 2020-06-06
whynotgonow 2020-06-03
陈旭阳 2020-06-02
88520191 2020-05-20
89500297 2020-05-16
前端开发Kingcean 2020-04-16
nmgxzm00 2020-11-10
xixixi 2020-11-11
MarukoMa 2020-09-02
88234852 2020-09-15
陈旭阳 2020-08-31
whynotgonow 2020-08-19
前端开发Kingcean 2020-07-30
whynotgonow 2020-07-29