小白对Promise的简单理解

464 阅读6分钟

一、Promise是什么?

1.抽象表达:

Promise是ES6定义的一门新的技术,为了解决异步编程的新解决方案。

2.具体表达:

(1)从语法来说:Promise就是一个构造函数 。

(2)从功能来说:Promise对象用来封装一个异步操作并得到其操作结果。

3.我的表达:

  • Promsie就是为了解决回调地狱的定义出来的一种方法。我们都知道代码有同步和异步俩种。同步简单来说就是同一时间只能干一件事,而异步表示同一时间可以干多件事。

  • 我们看下面一个例子简单描述同步和异步。

    (1)我们可以看到同步的输出结果。因为代码是从上往下顺序执行的,先调用b函数,所以会先输出“索子哥”。

    (2)异步中,我们给b函数加了一个定时器,这就导致“索子哥”是最后一个输出的。因为同步代码的运行时间很短很短,我们可以忽略不记,所以a、c函数会立即输出。所以但异步代码的执行是会花时间的。加了定时器的b函数就是一个异步代码。

  • 因为js是单线程的所以js引擎对代码进行执行过程中,碰到同步代码如a和c就会正常逐步进行,而碰到异步代码如b就会挂起,在同步代码都执行完成后,再进行异步代码的执行。

//同步
function a(){                                  
    console.log('盲仔');
}
function b(){ 

        console.log('索子哥');
    
}
function c(){

    console.log('石头人');
}

b()
a()
c()

输出:

索子哥
盲仔
石头人




//异步
function a(){
        console.log('盲仔');
}
function b(){ 
      setTimeout(() =>{
        console.log('索子哥');
    },1000)
    
}
function c(){
        console.log('石头人');
}

b()
a()
c()




输出:

盲仔
石头人
索子哥

二、Promise的用法

1. 在使用Promise方法前,我们先看下面一个例子

//代码1
function 相亲() {                            
        setTimeout(() => {
            console.log('索子哥相亲了');
        }, 2000)

}

function 结婚() {
        setTimeout(() => {
            console.log('索子哥结婚了');
        }, 1000)
}

function 生娃() {
     setTimeout(() => {
        console.log('小小索出生了');
    }, 500)  

}
           
相亲()  
结婚()
生娃()

//输出
小小索出生了
索子哥结婚了
索子哥相亲了

**对于这个代码我们给三个函数加了三个定时器,并且三个定时器的时间都不一样。
这就导致三个函数的输出顺序不一样,这就导致了索子哥还没相亲、结婚,小小索就出生了。
作为峡谷良好市民的索子哥,这好吗?这不好。
所以针对于此,我们用了以下的解决方法。**


//代码2
function 相亲() {
        setTimeout(() => {
            console.log('索子哥相亲了');
            结婚()
        }, 2000)

}

function 结婚() {
        setTimeout(() => {
            console.log('索子哥结婚了');
            生娃()
        }, 1000)
}

function 生娃() {
     setTimeout(() => {
        console.log('小小索出生了');
    }, 500)  

}
相亲()

//输出 
索子哥相亲了 
索子哥结婚了 
小小索出生了

**看到这个输出,索子哥终于笑了,找蛮王大战了三百回合。
  在相亲函数内调用结婚函数,在结婚函数内调用生娃函数,这就让函数逐步输出。
**

u=847096033,2602383311&fm=26&fmt=auto.webp

  • 但这个套娃式的回调方法调用多了之后,就会造成我们所说的回调地狱。那为了解决这种问题,我们有没有一种更简单,更优雅的方法来达到这种逐步输出的效果呢,为此。Promsie就来了。

2. Promise的基本使用

2.1 了解promise的三种状态:

  • pending: 初始状态,既不是成功,也不是失败状态。

  • fulfille: 意味着操作成功完成。

  • rejected: 意味着操作失败。

pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。

fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()

reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.then()或者.catch()

两种状态改变:

  1. pending 变为 fulfilled

  2. pending 变为 rejected

当我们 new Promise 的时候,此时的 Promise对象是 pending 状态,它可能会变为 fulfilled 状态并传递一个值给相应的状态处理方法,也可能变为 rejected 状态并传递失败信息。当其中任一种情况出现时,Promise 对象的 then 方法绑定的处理方法就会被调用。

2.2 promise 的基本流程

1974224-20200518105302435-692333170.png

2.3 promise对象的创建

const p = new Promise((resolve, reject) => { 
  console.log('执行 executor') //立刻执行
  resolve(value)
})

//promise 一定有resolve和reject两个参数,resolve表示成功成功,reject表示失败

我们还以索子哥为例,看下面的代码

function 相亲() {
    return new Promise((resolve, reject) => {  //首先创建一个新的promise对象
        setTimeout(() => {                     //然后执行异步代码
            console.log('索子哥相亲了');        //立刻执行
            resolve('OK')                      ////成功,调用resolve(value)
        }, 2000)

    })

}

function 结婚() {
        setTimeout(() => {
            console.log('索子哥结婚了');
        }, 1000)
}

相亲().then(结婚) 
    
  //输出
  索子哥相亲了
  索子哥结婚了
  
  我们可以看到输出结果依然是索子哥先相亲再结婚。
  
  
})
  • 注意点1: .then()方法必须要new完Promise对象后才能使用
  • 注意到2: 必须要调用resolve或reject函数 。 我们可以这么理解,promise中文是许诺的意思,resolve是索子哥相完亲想跟别人结婚做的承诺,只有做出了承诺,才能结婚。

2.4 promise的链式调用

  • 因为 Promise.prototype.then 和 Promise.prototype.catch 方法返回的是 promise 对象, 所以它们可以被链式调用。看下面代码。
function 相亲() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('索子哥相亲了');
            resolve()
        }, 2000)

    })

}

function 结婚() {
    return new Promise((resolve, reject)=>{
        setTimeout(() => {
            console.log('索子哥结婚了');
            resolve('okok')
        }, 1000)
    })
}

function 生娃() {
    return new Promise((resolve, reject)=>{
        setTimeout(() => {
           console.log('小小索出生了');
           resolve('okokok')
       }, 500)
   
    })
}

相亲()               //链式调用
.then(() =>{
   return  结婚()     
})
.then(() =>{
  return   生娃()
})

或者

相亲().then(结婚).then(生娃)

//输出 
索子哥相亲了 
索子哥结婚了 
小小索出生了

3. Promise 其他的一些基本用法

3.1 promise.then(iterable)、Promise.all(iterable)、Promise.race(iterable)

  • 需求:要让c后执行 //方法一 :a().then(b).then(c)
    我们都知道了第一种的方法按.then链式输出,所以输出顺序是a、b、c。

//方法二: Promise.all([a(),b()]).then(c)

Promise.all(iterable)的用法是里面放一个[ ],后面也可以接.then()。但必须是先执行完.all()里面的函数之后再执行后面的.then()。.all()里面的是谁执行时间短谁先执行。所以我们知道,b时间更短,所以输出顺序是先b再a再c,输出b、a、c。

//方法三:Promise.race([a(),b()]).then(c)

Promise.race(iterable)的有用法是优先执行.race()里面执行时间更短的函数,然后再执行.then()里面的函数,最后再执行.race()里面剩下位未执行的函数。从race这个单词就可以看出是竞速的意思。所以先执行b再执行c,最后执行a。输出顺序b、c、a。

function a() {
    return new Promise((resovle, result) => {
        setTimeout(() => {
            console.log('a');
            resovle('aaa')
        }, 2000)
    })

}
function b() {
    return new Promise((resovle, result) => {
        setTimeout(() => {
            console.log('b');
            resovle('bbb')
        }, 800)
    })

}
function c() {
    setTimeout(() => {
        console.log('c');
    }, 500)
}

//第一种                               //输出
// a().then(b).then(c)                 a、b、c
                                        
                                        
                                        

//第二种                              //输出    
// Promise.all([a(),b()]).then(c)      b、a、c

//弟三种                              //输出  
Promise.race([a(),b()]).then(c)        b、c、a
 

这些就是小白我对Promise的简单理解,不是很全面,大佬们多多指教

src=http___i0.hdslb.com_bfs_archive_18e0e3c6c46fde420de67ce7a811fdb86f959ebf.jpg&refer=http___i0.hdslb.jfif