Promise

Promise

回调函数
运行某个函数实现某个功能的时候,传入一个函数作为参数,当发生某件事情的时候,会执行该函数,由于JS中的函数是一等公民,它和其他数据类型一样,可以作为参数传递也可以作为返回值返回,所以经常能够看到回调函数使用。
例如

<button id="btn1">btn1:给btn2注册事件</button>
<button id="btn2">btn2:给btn3注册事件</button>
<button id="btn3">btn3:点击以后会弹出一个helloworld</button>
<script>
// 点击btn3弹出一个hello world
const btn1 = document.getElementById("btn1");
const btn2 = document.getElementById("btn2");
const btn3 = document.getElementById("btn3");
  btn1.addEventListener("click", function () {
   btn2.addEventListener("click",function(){
    btn3.addEventListener("click",function(){
     alert("hello world")
    })
   })
  })
</script>

回调地域
在异步实现中,回调函数的使用是不可避免的。JS的异步是单线程非阻塞式的。它将一个异步动作分为两步,第一步执行异步方法,然后代码接着往下执行。然后在后面的某个时刻调用第二步的回调函数,完成后续动作。
有的时候,我们希望在异步操作中加入同步的行为。比如,我想打印4句话,但是每句话都在前一句话的基础上延迟2秒输出。代码如下:

setTimeout(function(){
    console.log("first");
    setTimeout(function(){
        console.log("second");
        setTimeout(function(){
            console.log("third");
            setTimeout(function(){
                console.log("fourth");
            },2000);
        },2000);
    },2000);
},2000);

这段代码能够实现想要的功能,但是如果输出的内容越来越多,嵌套的代码也会增多。某个异步操作需要等待之前的异步操作完成,无论回调是事件还是其他函数,都会陷入不断的嵌套,这样就会越套越多,代码越来越来复杂,俗称“回调地狱”。

Promise
为了解决这个问题,在ES6中加入了一个新的对象Promise。
Promise并不是消除回调,只是让回调变得更简单,变更可控

new Promise(function(resolve,reject){
    //dosomething
});

首先需要创建一个Promise对象,该对象的构造函数中接收一个回调函数,回调函数中可以接收两个参数,resolve和reject。注意,这个回调函数是在Promise创建后就会调用。它实际上就是异步操作的第一步。Promise把两个步骤分开了,第二步通过Promise对象的then方法实现。

let pm = new Promise(function(resolve,reject){
    //dosomething
});
console.log("go on");
pm.then(function(){
    console.log("异步完成");
});

注意 then方法的回调函数不是说只要then方法一调用它就会调用,而是在Promise的回调函数中通过调用resolve触发的。

let pm = new Promise(function(resolve,reject){
    resolve();
});
console.log("go on");
pm.then(function(){
    console.log("异步完成");
});

实际上Promise实现异步的原理和之前纯用回调函数的原理是一样的。只是Promise的做法是将两个步骤分开来写。then方法的回调函数同样会先放入队列中,等待所有的同步方法执行完后,同时Promise中的resolve也被调用后,该回调函数才会执行。
reject是出现错误时调用的方法。它触发的不是then中的回调函数,而是catch中的回调函数。比如:

let err = false;
let pm = new Promise(function(resolve,reject){
    if(!err){
        resolve("this is data");
    }else{
        reject("fail");
    }

});
console.log("go on");
pm.then(function(data){
    console.log("异步完成",data);
});
pm.catch(function(err){
    console.log("出现错误",err);
});

时间函数的异步操作用Promise实现

let timeout = function(time){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve();
        },time);
    });
}
console.log("go on");
timeout(2000).then(function(){
    console.log("first");
    return timeout(2000);
}).then(function(){
    console.log("second");
    return timeout(2000);
}).then(function(){
    console.log("third");
    return timeout(2000);
}).then(function(){
    console.log("fourth");
    return timeout(2000);
});

由于需要多次创建Promise对象,所以用了timeout函数将它封装起来,每次调用它都会返回一个新的Promise对象。当then方法调用后,其内部的回调函数默认会将当前的Promise对象返回。后面继续用then方法来触发异步完成的回调函数。这样就可以做到同步的效果,从而避免了过多的回调嵌套带来的“回调地狱”问题。

参考:https://zhuanlan.zhihu.com/p/74637286

finally()
ES2018出来的,没有参数的,当promise为已决时运行该函数
Promise.all()
方法用于将多个 Promise 实例 这个方法会返回一个新的promise对象,如果里面所有的promise对象都成功才会触发,一旦有一个失败,则该promise对象为失败

const proms = [];
  for(let i = 0;i < 10;i ++){
   proms.push(new Promise((resolve,reject) => {
    // resolve(1)
    setTimeout( ()=> {
     if(Math.random() < 0.9){
      console.log(i,"完成")
      resolve(i)
     }else{
      console.log(i,"失败")
      reject(i)
     }
    },1000)
   }))
  }
  // 所有的都成功才为成功,只要有一个失败,就失败
  const pro = Promise.all(proms);
  pro.then(data => {
   console.log('全部完成',data);
  })
  pro.catch(err => {
   console.log('有失败的',err)
  })

Promise.race()
方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。当参数中的任意一个promise对象完成时候,就马上回去使用完成的这个promise对象的结果,不管这个结果成功还是失败

function getRandom(min,max){
   return Math.floor(Math.random() * (max - min) + min)
  }
  const proms = [];
  for(let i = 0;i < 10;i ++){
   proms.push(new Promise((resolve,reject) => {
    // resolve(1)
    setTimeout( ()=> {
     if(Math.random() < 0.9){
      console.log(i,"完成")
      resolve(i)
     }else{
      console.log(i,"失败")
      reject(i)
     }
    },getRandom(1000,5000))
   }))
  }
  const pro = Promise.race(proms);
  pro.then(data => {
   console.log('有人完成了',data);
  })
  pro.catch(err => {
   console.log('有失败的',err)
  })
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值