Promise是什么?怎么使用? 如何实现一个简易版的Promise?

Promise 是什么?

mdn:Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。
既然Promise是为了表示异步的最终结果,那异步是什么呢?为啥要用Promise来表示异步的结果?而不用其他方式呢?

什么是异步

用一个例子来说明
当你在餐厅吃饭,首先你得先去排队拿号,
但是,你前面还有10桌需要等待,可能需要几十分钟,
如果你在这里傻等,那就是同步操作,
但正常人没那么傻,大部分人都是先拿票,然后去点其他事情,这就是异步操作
那如何知道是否轮到自己?

  1. 隔一会去拿票的地方问(轮询)
  2. 用微信小程序接收通知(回调)

异步即立即拿不到结果需要通过回调和轮询来获取异步操作的结果
下面是一些异步操作的典型案例

  1. setTimeout
  2. AJAX
  3. AddEventListener
获取异步的结果
  1. 回调callback
    用微信小程序接收通知
function 排队(号码, 到我了吗){
    if(号码轮到我了){
        return 到我了吗('快来吃饭啦');
    }
  }
  function 到我了吗(到我了吗){
    return '快来吃饭啦';
  }
  1. 轮询
    隔一会去拿票的地方问
//设置定时器,每隔20分钟去问一次
const 排队吃饭 = setInterval(() => {
    if (结果 === '到我啦') {
        //到我了就去吃饭,清除计时器,停止轮询
        clearInterval(this.timeId)
    }; 
    问前台轮到我了吗();
}, 1000*60*20)
为啥要使用Promise

既然轮询和回调都可以拿到结果,为啥要用promise呢
异步的结果可能会有两种,一是成功,二是失败,所以我们要么使用两个回调,要么回调接收两个参数

//回调接受两个参数
fs.readFile('./1.txt', (error, data) => {
    if (error) {
        console.log('失败');//失败返回失败信息
        return
    }
    console.log(data.toString())//成功返回数据结果
})
//用两个回调来接受结果
ajax('get','/1.json', data=>{}, error=>{})
//回调地狱(仅4层的回调?如果更多呢?)
getUser(user => {
    getGroups(user, (groups) => {
        groups.forEach((g) => {
            g.filter(x => x.ownerId === user.id)
                .forEach(x => console.log(x))
        })
    })
})

缺点:

  1. 回调参数的命名没有明确规定
  2. 回调一多,容易出现回调地狱
  3. 很难进行错误处理
Promise

前面两种方法都有一些缺陷,而Promise的设计思想刚好又解决了这些缺陷
Promise的原理:使用resolve, reject两个函数控制Promise内部成功和失败状态,promise.then()根据成功和失败执行不同的函数,实现异步

  1. 创建Promise对象
new Promise((resolve,reject)=>{})
  1. Promise.prototype.then
//通过then函数传入成功和失败的执行操作,success不可省略,fail可省略
new Promise((resolve,reject)=>{}).then(success,fail)
  1. Promise.all
    将多个Promise实例包装成一个新的Promise实例,实例全部成功则返回数组,实例失败则返回第一个失败的状态值
Promise.all可以let obj = new Promise((resolve,reject)=>{resolve('成功')})
let obj1 = new Promise((resolve,reject)=>{resolve('成功')})
let obj2 = new Promise((resolve,reject)=>{reject('失败')})
//执行结果["成功", "成功"]
Promise.all([obj,obj1]).then((result) => {
  console.log(result)
}).catch((error) => {
  console.log(error)    
})
//执行结果 失败
Promise.all([obj,obj2]).then((result) => {
  console.log(result)
}).catch((error) => {
  console.log(error)    
})
  1. promise.race,获取多个实例中执行最快的那个实例的返回结果(不管处于成功状态和失败状态)
let obj = new Promise((resolve,reject)=>{
   setTimeout(() => {
       resolve('成功')
     }, 500)
   
})
let obj1 = new Promise((resolve,reject)=>{
   setTimeout(() => {
       reject('失败')
     }, 1000)   
})
//由于obj的执行时间较快,执行结果成功
Promise.race([obj,obj1]).then((result) => {
 console.log(result)
}).catch((error) => {
 console.log(error)    
})
手写简易版Promise

实现思路:Promise内部定义两个队列,用于存放用户传过来的成功或失败之后的函数,提供resolve和reject用于成功和失败之后执行队列中的函数

class Promise2{
    //创建两个队列用于存放成功或失败后要执行的函数
    queue1 = []
    queue2 = []
    constructor(fn){
        //成功函数
        const resolve = (data) =>{
            //执行队列中的函数
            setTimeout(()=>{
                for(let i =0;i< this.queue1.length;i++){
                    this.queue1[i](data)
                }
            })
        }
        //失败函数
        const reject = (reason) =>{
            setTimeout(()=>{
                for(let i = 0; i< this.queue2.length;i++){
                    this.queue2[i](reason)
                }
            })
        }
        fn(resolve,reject);
    }
    then(s,e){
        this.queue1.push(s);
        this.queue2.push(e);
        return this
    }
}

var p1 = new Promise2((resolve,reject)=>{console.log('hi');resolve();})
p1.then(()=>{ console.log('成功')})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值