Promise

es一种技术,解决异步回调,解决回调地狱

为什么要使用Promise

  • promise是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外)

  • 并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据

  • 代码风格,容易理解,便于维护

  • 多个异步等待合并便于解决

如何使用Promise

三个状态:

  • pending
  • fulfilled
  • rejected
new Promise(function (resolve, reject) {
    // 一段耗时的异步操作
    resolve('成功')   // 数据处理完成
    // reject('失败') // 数据处理出错
  }
).then(
    // resolved状态的回调函数
    res => console.log(res),  // 成功
    // rejected状态的回调函数
    err => console.log(err)   // 失败
)

Promise原理是怎么实现的

function Promise(executor){
    let that = this;
    that.status = 'pending';
    that.resolveValue = undefined;
    that.rejectValue = undefined;
    function resolve(value){
        if(that.status === 'pending'){
            that.status = 'resolved';
            that.resolveValue = value;
        }
    }
    function reject(value){
        if(that.status = 'pending'){
            that.status = 'rejected';
            that.rejectValue = value;
        }
    }
    // executor执行器
    executor(resolve, reject);
}

Promise.prototype.then = function(onFufiled, onRejected){
    let that = this;
    if(that.status === 'resolved'){
        onFufiled(that.resolveValue);
    }
    if(that.status === 'rejected'){
        onRejected(that.rejectValue);
    }
}

then()

指定resolved和rejected状态的回调函数

Promise是一个构造函数,原型上也有then、catch、finally方法,.then()方法返回一个新的promise实例,因此可以链式结构

catch()

.then(undefined, rejection)或.then(null, rejection)的别名,即then的第二个回调函数,推荐写法,因为会捕获前边所有then方法的错误

用法同.then(),用来捕获错误信息,同样返回一个promise实例,继续.then()链式操作

const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // 下面一行会报错,因为x没有声明
    resolve(x + 2);
  });
};

someAsyncThing()
.catch(function(error) {
  console.log('oh no', error);
})
.then(function() {
  console.log('carry on');
});
// oh no [ReferenceError: x is not defined]
// carry on

finally()

不管状态如何,成功与否,都会执行的操作

new Promise(() => {}).finally(() => {})

//then方法的特例 等同于  
new Promise(function (resolve, reject) {
    // 一段耗时的异步操作
    resolve('成功')   // 数据处理完成
    reject('失败') // 数据处理出错
  }
).then(
    res => {return res},  
    err => {throw err}   
)
Promise
.resolve()
.then(result => console.log(111))
.catch(error => console.log(222))
.finally(() => console.log(333))
// 111
// 333

Promise
.reject()
.then(result => console.log(111))
.catch(error => console.log(222))
.finally(() => console.log(333))
// 222 333

all()

将多个promise实例,包装成一个promise实例

p的状态由p1、p2、p3决定

  • p1、p2、p3都成功,p才成功

  • p1、p2、p3中有一个失败,p失败

const p1 = new Promise(resolve => resolve('p1成功'))
const p2 = new Promise(resolve => resolve('p2成功'))
const p3 = new Promise(resolve => resolve('p3成功'))

const p = Promise.all([p1, p2, p3])
// Promise {<resolved>: Array(3)}
const p6 = new Promise((resolve,reject) => reject('p6失败'))

const p = Promise.all([p1, p2, p3, p6]) 
// Uncaught (in promise) p6失败

注意:

如果作为参数的Promise实例,自己定义了catch方法,被rejected之后,就不会触发Promise.all()的catch方法,因为Promise实例的catch方法会返回一个新的promise,会继续调用then方法

const p1 = new Promise((resolve, reject) => {
    resolve('hello')
})
.then(result => result)
.catch(e => e)

const p2 = new Promise((resolve, reject) => {
    throw new Error('error')
})
.then(result => result)
.catch(e => e)

Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e))
// ["hello", Error: error]

如果p2没有catch方法,就会调用Promise.all()的catch方法

const p5 = new Promise((resolve, reject) => {
    resolve('hello')
})
.then(result => result)
.catch(e => e)

const p6 = new Promise((resolve, reject) => {
    throw new Error('error')
})
.then(result => {
    return result
})

Promise.all([p5, p6])
.then(result => console.log(result))
.catch(e => console.log(e))
// Error: error

race()

将多个Promise实例包装成一个新的Promise实例返回,用法同all(),作用:将作为参数的Promise实例率先改变状态的值返回

const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => resolve('p1'), 3000)
})
const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => resolve('p2'), 1000)
})
const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => resolve('p3'), 2000)
})
Promise.race([promise1, promise2, promise3])
.then(result => console.log(result))
.catch(error => console.log(error))
Promise {<pending>}
// p2

allSettled()

用法同上,接受一组Promise实例,作用:等所有Promise实例状态都改变(不管成功还是失败),才会执行allSettled方法

any()

将多个promise实例,包装成一个promise实例

p的状态由p1、p2、p3决定

  • p1、p2、p3有一个成功,p就成功

  • p1、p2、p3都失败,p才失败

resolve()

将现有对象转为Promise对象,相当于Promise实例的resolve

Promise.resolve('foo')
.then(result => console.log(result))
// foo

//等同于
new Promise(resolve => resolve('foo'))
.then(result => console.log(result))
// foo

reject()

相当于执行Promise实例的reject

Promise.reject('error')
.catch(error => console.log(error))
// error

// 相当于
new Promise((resolve, reject) => {
    reject('error')
})
.then(null, error => console.log(error))
// error

应用

  • 图片加载:加载完成调用resolve方法,改变Promise状态
const imgLoad = (path) => {
    return new Promise((resolve, reject) => {
        const img = new Image()
        img.onload = resolve
        img.onerror = reject
        img.src = path
    })
}

results matching ""

    No results matching ""