• promise


    Promise是什么?
    Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一。这句话说的很明白,Promise是一种用于解决异步问题的思路,方案或者对象方式。在js中,经常使用异步的地方是ajax交互。比如在es5时代,jQuery的ajax的使用success来完成异步的:
    $.ajax({
    url:'/xxx',
    success:()=>{},
    error:()=>{}
    })
    这种方法可以清楚的让读代码的人明白那一部分是Ajax请求成功的回调函数和失败的回调函数,但是问题来了,当一次性需要请求多个接口时,
    $.ajax({
    url:'/xxx',
    success:()=>{
    // 第二次
    $.ajax({
    url:'/xxx',
    success:()=>{
    // 第三次
    $.ajax({
    url:'/xxx',
    success:()=>{
    // 可能还会有
    },
    error: ()=>{}
    })
    },
    error: ()=>{}
    })
    },
    error: ()=>{}
    })
    es6时代,promise的出现给异步带来了变革。
    Promise提供一个then,来为异步提供回调函数
    $.ajax({
    url:'/xxx',
    }).then(()=>{
    //成功的回调
    },()=>{
    //回调失败
    })

    Promise的用法
    Promise是一个对象,因此,我们使用new的方式新建一个。然后给他传一个函数作为参数,这个函数也有两个参数,一个叫resolve(决定),一个叫reject(拒绝),这两个参数也是函数。我们使用then来调用这个Promise:
    const fn=new Promise(function(resolve,reject){
    setTimeout(()=>{
    let num=Math.ceil(Math.random()*10)
    if(num>5){
    resolve(num)
    }else{
    reject(num)
    }
    },2000)
    })
    fn.then(res)=>{
    console.log(res);
    },(err)=>{
    console.log(err);
    }

    Promise的原理
    在Promise的内部,有一个状态管理器的存在,有三种状态:pending(在等待…期间),fulfilled,rejected.
    (1) promise对象初始化状态为pending。
    (2)当调用resolve(成功),会有pending=》fulfilled
    (3)当调用reject(失败),会由pending=>rejected

    Promise的几种方法
    then方法用于注册当前状态变为fulfilled或者reject时回调函数
    promise.then(onFulfilled,onRejected);
    //onFulfilled用来接收promise成功的值
    //onRejected用来接收promise失败的原因
    // resolve(成功) onFulfilled会被调用

    then方法是异步执行的。
    const promise = new Promise((resolve, reject) => {
    resolve('fulfilled'); // 状态由 pending => fulfilled
    });
    promise.then(result => { // onFulfilled
    console.log(result); // 'fulfilled'
    }, reason => { // onRejected 不会被调用
    })

    // reject(失败) onRejected会被调用
    const promise = new Promise((resolve, reject) => {
    reject('rejected'); // 状态由 pending => rejected
    });
    promise.then(result => { // onFulfilled 不会被调用
    }, reason => { // onRejected
    console.log(rejected); // 'rejected'
    })

    catch
    fn = new Promise(function (resolve, reject) {
    let num = Math.ceil(Math.random() * 10)
    if (num > 5) {
    resolve(num)
    } else {
    reject(num)
    }
    })
    fn.then((res)=>{
    console.log(res)
    }).catch((err)=>{
    console.log(`err==>${err}`)
    })

    all
    var p1=Promise.resolve(1),
    p2=Promise.reject(2),
    p3=Promise.resolve(3)
    Promise.all([p1,p2,p3]).then((res)=>{
    console.log(results);
    }).catch((err)=>{
    console.log(err);
    })
    大概作为参数的几个promise对象一旦有一个状态为rejected,则all的返回值就是rejected。
    当这几个作为参数的函数的返回状态为fulfilled时,至于输出的时间就要看谁跑的慢了:
    let p1 = new Promise((resolve)=>{
    setTimeout(()=>{
    console.log('1s') //1s后输出
    resolve(1)
    },1000)
    })
    let p10 = new Promise((resolve)=>{
    setTimeout(()=>{
    console.log('10s') //10s后输出
    resolve(10)
    },10000)
    })
    let p5 = new Promise((resolve)=>{
    setTimeout(()=>{
    console.log('5s') //5s后输出
    resolve(5)
    },5000)
    })
    Promise.all([p1, p10, p5]).then((res)=>{
    console.log(res); // 最后输出
    })
    这段代码运行时,根据看谁跑的慢的原则,则会在10s之后输出[1,10,5]。over,all收工。

    race
    promise.race()方法也可以处理一个promise实例数组但它和promise.all()不同,从字面意思上理解就是竞速,那么理解起来上就简单多了,也就是说在数组中的元素实例那个率先改变状态,就向下传递谁的状态和异步结果。但是,其余的还是会继续进行的。
    let p1 = new Promise((resolve)=>{
    setTimeout(()=>{
    console.log('1s') //1s后输出
    resolve(1)
    },1000)
    })
    let p10 = new Promise((resolve)=>{
    setTimeout(()=>{
    console.log('10s') //10s后输出
    resolve(10) //不传递
    },10000)
    })
    let p5 = new Promise((resolve)=>{
    setTimeout(()=>{
    console.log('5s') //5s后输出
    resolve(5) //不传递
    },5000)
    })
    Promise.race([p1, p10, p5]).then((res)=>{
    console.log(res); // 最后输出
    })

    用js实现一个简单的promise
    function Promise(fn){
    var status = 'pending';
    function successNotify(){
    status='fulfilled'//状态变为fulfilled
    toDoThen.apply(undefined,arguments) //执行回调
    }
    function failNotify(){
    status='rejectd' //状态变为rejected
    toDoThen.apply(undefined,arguments) //执行回调
    }
    function toDoThen(){
    setTimeout(()=>{ //保证回调是异步执行的
    if(status==='fulfilled'){
    for(let i=0;i<successArray.length;i++){
    successArray[i].apply(undefined,arguments) //执行then里面的回掉函数
    }
    }else if(status==='rejected'){
    for(let i=0;i<failArray.length;i++){
    failArray[i].apply(undefined,arguments) //执行then里面的回掉函数
    }
    }
    })
    }
    var successArray=[];
    var failArray=[];
    fn.call(undefined,successNotify,failNotify);
    return {
    then:function(successFn,failFn){
    successArray.push(successFn)
    failArray.push(failFn)
    return undefined
    }
    }
    }

  • 相关阅读:
    关于连通性问题的Tarjan算法暂结
    【BZOJ 3925】[Zjoi2015]地震后的幻想乡 期望概率dp+状态压缩+图论知识+组合数学
    Kruskal算法及其类似原理的应用——【BZOJ 3654】tree&&【BZOJ 3624】[Apio2008]免费道路
    【NOIP模拟赛】Drink 二维链表+模拟
    【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护
    【BZOJ 4198】[Noi2015]荷马史诗 哈夫曼编码
    【NOIP模拟赛】chess 建图+spfa统计方案数
    【TMD模拟赛】上低音号 链表
    【TMD模拟赛】黄金拼图 Cao
    【BZOJ 4007】[JLOI2015]战争调度 DP+搜索+状压
  • 原文地址:https://www.cnblogs.com/zhihou/p/10288440.html
Copyright © 2020-2023  润新知