微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Promise 学习笔记

目录

1. Promise 基本结构

2. Promise 状态和值

3. Promisethen 方法

4. Promise基本实现

5. Promise零碎知识


Promise 用法MDN Promise
Promise 底层实现Promise实现原理(附源码) (本文学习并参考的一篇博客,推荐直接阅读)
其他推荐Promise简单实现

@H_502_29@

(一)Promise 基本结构

Promise 是一种抽象异步处理对象,其核心概念为 “确保一件事做完之后,再做另一件事”@H_502_29@

new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('FULFILLED')
  }, 1000)
})

构造函数Promise必须接受一个函数作为参数,称该函数handlehandle又包含resolvereject两个参数,它们是两个函数。@H_502_29@

(二) Promise 状态和值

Promise 对象存在以下三种状态:@H_502_29@

  • Pending (进行中)
  • Fulfilled (已成功)
  • Rejected(已失败)

状态只能由 Pending 变为 Fulfilled 或由 Pending 变为 Rejected ,且状态改变之后不会在发生变化,会一直保持这个状态。@H_502_29@

Promise的值是指状态改变时传递给回调函数的值.@H_502_29@

上文中handle函数包含 resolvereject 两个参数,它们是两个函数,可以用于改变 Promise 的状态和传入 Promise 的值。@H_502_29@

  • resolve : 将Promise对象的状态从 Pending(进行中) 变为 Fulfilled(已成功)`
  • reject : 将Promise对象的状态从 Pending(进行中) 变为 Rejected(已失败)`
  • resolve :和 reject 都可以传入任意类型的值作为实参,表示 Promise 对象成功(Fulfilled)和失败(Rejected)的值

在Promise构造函数handle中可以执行一些处理(可以是异步处理),如果执行结果正常则调用resolve回调函数,否则调用reject回调函数。在ES6中将“执行结果正常” 称为Promise对象返回肯定结果,将 “执行失败” 称为Promise对象返回否定结果。@H_502_29@

(三)Promisethen 方法

promise.then(onFulfilled, onRejected)

Promise 对象的 then 方法接受两个参数,onFulfilledonRejected 都是可选参数。@H_502_29@

多次调用then 方法可以被同一个 promise 对象调用多次@H_502_29@

  • promise 成功状态时,所有 onFulfilled 需按照其注册顺序依次回调
  • promise 失败状态时,所有 onRejected 需按照其注册顺序依次回调

返回then 方法必须返回一个新的 promise 对象@H_502_29@

promise2 = promise1.then(onFulfilled, onRejected);

因此 promise 支持链式调用@H_502_29@

promise1.then(onFulfilled1, onRejected1).then(onFulfilled2, onRejected2);

1. onFulfilled 特性

(1)onFulfilled 不是函数:@H_502_29@

  • onFulfilled 将被忽略。@H_502_29@

  • onFulfilled 不是函数promise1 状态为成功(Fulfilled)时, promise2 必须变为成功(Fulfilled)并返回 promise1 成功的值。@H_502_29@

    let promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('success')
      }, 1000)
    })
    promise2 = promise1.then('这里的onFulfilled本来是一个函数,但现在不是')
    promise2.then(res => {
      console.log(res) // 1秒后打印出:success
    }, err => {
      console.log(err)
    })
    

(2)onFulfilled函数:@H_502_29@

  • promise 状态变为成功时必须被调用,其第一个参数为 promise 成功状态传入的值( resolve 执行时传入的值)@H_502_29@

  • promise 状态改变前其不可被调用@H_502_29@

  • 调用次数不可超过一次@H_502_29@

  • 如果 onFulfilled 返回一个x ,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)@H_502_29@

    • x 不为 Promise ,则使 x 直接作为新返回的 Promise 对象的值, 即新的onFulfilled 或者 onRejected 函数的参数.@H_502_29@

    • xPromise ,这时后一个回调函数,就会等待该 Promise 对象(即 x )的状态发生变化,才会被调用,并且新的 Promise 状态和 x 的状态相同。@H_502_29@

    // 当onFulfilled返回值不为Promise:
    let promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve()
      }, 1000)
    })
    promise2 = promise1.then(res => {
      // 返回一个普通值
      return '这里返回一个普通值'
    })
    promise2.then(res => {
      console.log(res) //1秒后打印出:这里返回一个普通值
    })
    
    // 当onFulfilled返回值为Promise:
    let promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve()
      }, 1000)
    })
    promise2 = promise1.then(res => {
      // 返回一个Promise对象
      return new Promise((resolve, reject) => {
        setTimeout(() => {
         resolve('这里返回一个Promise')
        }, 2000)
      })
    })
    promise2.then(res => {
      console.log(res) //3秒后打印出:这里返回一个Promise
    })
    
  • 如果 onFulfilled 抛出一个异常 e ,则 promise2 必须变为失败(Rejected),并返回失败的值 e@H_502_29@

    let promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('success')
      }, 1000)
    })
    promise2 = promise1.then(res => {
      throw new Error('这里抛出一个异常e')
    })
    promise2.then(res => {
      console.log(res)
    }, err => {
      console.log(err) //1秒后打印出:这里抛出一个异常e
    })
    

2. onRejected 特性

(1)onRejected 不是函数:@H_502_29@

  • onRejected 将被忽略。@H_502_29@

  • onRejected 不是函数promise1 状态为失败(Rejected)promise2必须变为失败(Rejected) 并返回 promise1 失败的值。@H_502_29@

let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('fail')
  }, 1000)
})
promise2 = promise1.then(res => res, '这里的onRejected本来是一个函数,但现在不是')
promise2.then(res => {
  console.log(res)
}, err => {
  console.log(err)  // 1秒后打印出:fail
})

(2)onRejected函数@H_502_29@

  • promise 状态变为失败时必须被调用,其第一个参数为 promise 失败状态传入的值( reject 执行时传入的值)@H_502_29@

  • promise 状态改变前其不可被调用@H_502_29@

  • 调用次数不可超过一次@H_502_29@

  • 如果onRejected 返回一个x ,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)@H_502_29@

    • x 不为 Promise ,则使 x 直接作为新返回的 Promise 对象的值, 即新的onFulfilled 或者 onRejected 函数的参数.@H_502_29@

    • xPromise ,这时后一个回调函数,就会等待该 Promise 对象(即 x )的状态发生变化,才会被调用,并且新的 Promise 状态和 x 的状态相同。@H_502_29@

  • 如果onRejected 抛出一个异常 e ,则 promise2 必须变为失败(Rejected),并返回失败的值 e@H_502_29@

(四)Promise基本实现

下面代码仅实现Promiseresolverejectthen方法。@H_502_29@

// 判断变量否为function
const isFunction = variable => typeof variable === 'function'
// 定义Promise的三种状态常量
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'

//定义一个名为 MyPromise 的 Class,它接受一个函数 handle 作为参数
class MyPromise {
    constructor (handle) {
      if (!isFunction(handle)) {
        throw new Error('MyPromise must accept a function as a parameter')
      }
      // 添加状态
      this._status = PENDING
      // 储存then回调return的值
      this._value = undefined
       // 这里之所以使用队列来储存回调,是为了实现规范要求的 "then 方法可以被同一个 promise 调用多次"
      // 添加成功回调函数队列,resolve时触发
      this._fulfilledQueues = []
      // 添加失败回调函数队列,reject时触发
      this._rejectedQueues = []
      // 执行handle
      try {
        handle(this._resolve.bind(this), this._reject.bind(this)) 
      } catch (err) {
        this._reject(err)
      }
    }
    // 添加resovle时执行的函数
    _resolve (val) {
      if (this._status !== PENDING) return // 对应规范中的"状态只能由pending到fulfilled或rejected"
      // 依次执行成功队列中的函数,并清空队列
      const run = () => {
        this._status = FULFILLED  // 变更状态
        this._value = val  // 储存当前value
        while (this._fulfilledQueues.length) {
        	const cb = this._fulfilledQueues.shift()
        	cb(val)
        }

      }
      // 为了支持同步的Promise,这里采用异步调用
      setTimeout(run)
    }
	// 添加reject时执行的函数
	_reject (err) { 
	  if (this._status !== PENDING) return
	  // 依次执行失败队列中的函数,并清空队列
	  const run = () => {
	    this._status = REJECTED
	    this._value = err
        while (this._rejectedQueues.length) {
        	const cb = this._rejectedQueues.shift()
        	cb(val)
        }

	  }
	  // 为了支持同步的Promise,这里采用异步调用
	  setTimeout(run)
	}
  // 添加then方法
	then (onFulfilled, onRejected) {
	  const { _value, _status } = this
	  // 返回一个新的Promise对象
	  return new MyPromise((onFulfillednext, onRejectednext) => {
	    // 封装一个成功时执行的函数
	    let fulfilled = value => {
	      try {
	        if (!isFunction(onFulfilled)) {
	          onFulfillednext(value)
	        } else {
	          let res =  onFulfilled(value);
	          if (res instanceof MyPromise) {
	            // 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
	            res.then(onFulfillednext, onRejectednext)
	          } else {
	            //否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
	            onFulfillednext(res)
	          }
	        }
	      } catch (err) {
	        // 如果函数执行出错,新的Promise对象的状态为失败
	        onRejectednext(err)
	      }
	    }
	    // 封装一个失败时执行的函数
	    let rejected = error => {
	      try {
	        if (!isFunction(onRejected)) {
	          onRejectednext(error)
	        } else {
	            let res = onRejected(error);
	            if (res instanceof MyPromise) {
	              // 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
	              res.then(onFulfillednext, onRejectednext)
	            } else {
	              //否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
	              onFulfillednext(res)
	            }
	        }
	      } catch (err) {
	        // 如果函数执行出错,新的Promise对象的状态为失败
	        onRejectednext(err)
	      }
	    }
	    switch (_status) {
	      // 当状态为pending时,将then方法回调函数加入执行队列等待执行
	      case PENDING:
	        this._fulfilledQueues.push(fulfilled)
	        this._rejectedQueues.push(rejected)
	        break
	      // 当状态已经改变时,立即执行对应的回调函数
	      case FULFILLED:
	        fulfilled(_value)
	        break
	      case REJECTED:
	        rejected(_value)
	        break
	    }
	  })
	}

}

(五)零碎知识

Promise类的all方法

  • Promise类的all方法可以并行执行多个异步处理。
  • Promise.all方法一个Promise对象数组作为参数,并创建一个当所有执行结果都成功时返回肯定结果的Promise对象。在该对象的then方法中可以得到一个结果数组result,无论该对象的肯定结果为何,该结果数组与传入的Promise对象数组顺序保持一致。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐