Promise学习笔记-二

Promise运行流程

promise运行流程.jpg

Promise有pending(进行中)、fulfilled(已完成)、rejected(已失败)三种状态。它们有两种状态转变过程:

  • 第一,由pending状态到fulfilled,通过resolve进行处理
  • 第二,由pending到rejected,通过reject进行处理。

由于resolve处理异步时传入的参数为实例本身时,程序也会抛出异常进行reject来结束程序执行。先看一下JavaScript的异常有哪几种类型

JavaScript的异常类型

  1. Error:最基本的错误类型。其他错误的类型都继承自该类型。(程序运行过程中抛出的异常一般都有具体类型,Error类型一般都是开发人员自己抛出的异常)
  2. SyntaxError:语法错误,也称解析错误。表示不符合编程语言的语法规范。JavaScript是一门解释性语言,代码执行时需要经历词法分析->语法分析->语法树。词法分析是将字符流(char stream)转换为记号流(token stream)、语法分析阶段会将记号流(token stream)生成抽象语法树(AST)。在这两个阶段如果JavaScript引擎发现了预期之外/无法转换的token或者token顺序和预期不一致时就会抛出SyntaxError。
  3. TypeError:类型错误。表示参数或变量不是预期的类型。
  4. ReferenceError:引用错误。引用一个不存在的变量发生的错误,每当创建或定义一个变量时,变量名都会写入一个变量储存中心,这个变量储存中心就像键值存储一样,每当引用变量时,它都会去存储中找到Key并提取返回Value,如果要找的变量不在存储中,就会抛出ReferenceError
  5. RangError:边界错误。表示超出有效范围时发生的异常
  6. URIError:URL错误。在调用URI相关的方法中URL无效时抛出的异常。主要包括encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()几个函数

Promise的源码实现

  • Promise构造函数
function noop () {}
function Promise (fn) {
    // 判断Promise是否new关键字进行实例化
    if (!(this instanceof Promise)) {
        throw new TypeError('Promise must be constructed via new')
    }
    // Promise在实例化时的参数必须是个函数
    if (typeof fn !== 'function') {
        throw new TypeError('Promise constructor\'s arguments is not a function')
    }
    // noop是个空函数,如果传入的fn为noop不做任何操作
    if (fn === noop) return
    // Promise 延迟执行状态
    this._deferredState = 0
    // Promise 执行状态
    this._state = 0;
    // Promise执行结果
    this._value = null;
    // 延迟处理存储(数组)
    this._deferreds = null;
    // 实现内部绑定
    doResolve(fn, this)
}
复制代码

Promise构造函数内部主要是对Promise实例化方式、实例化时Promise传入参数进行验证。接下来是定义Promise内部的运行状态、运行结果等的变量。_deferredStatePromise内部应用了另外一个promise时的延迟执行状态;_statePromise实例本身运行状态;_valuePromise实例本身运行结果;_deferredsPromise内部调用异步处理任务时,存储延迟处理函数,当签Promise的resolve或reject被调用后才去执行这里面的方法。doResolve()方法主要实现实例化时Promise所传回调函数及函数参数resolve和reject的方法绑定。

  • doResolve
var LAST_ERROR = null
var IS_ERROR = {}
// tryCallTwo将Promise的回调函数的两个参数转化为处理方法
function tryCallTwo(fn, a, b) {
    try {
        fn (a, b)
    } catch (ex) {
        LAST_ERROR = ex
        return IS_ERROR
    }
}
function doResolve (fn, promise) {
    // 初始完成状态为false
    var done = false;
    // 将实例Promise时传入的resolve和reject的内部实现
    var res = tryCallTwo(fn, function (value) {
        // 如果已完成,停止执行
        if (done) return;
        // 未完成将done设为true,以待下次判断
        done = true;
        // 调用resolve处理方法
        resolve(promise, value);
    }, function (reason) { // reject内部实现
        if (done) return;
        done = true;
        // 调用reject处理方法
        reject(promise, reason);
    });
    // tryCallTwo方法抛出异常时,将done设为true,调用reject处理程序
    if (!done && res === IS_ERROR) {
        done = true;
        reject(promise, LAST_ERROR);
    }
}
复制代码

仿写以上代码

var LAST_ERROR = null
var IS_ERROR = {}
function noop () { }
function tryCallTwo (fn, a, b) {
    try {
        fn(a, b)
    } catch (ex) {
        LAST_ERROR = ex
        return IS_ERROR
    }
}
function doResolve (fn, promise) {
    var done = false
    var res = tryCallTwo(fn, function (value) {
        if (done) return
        done = true
        // resolve(promise, value)
    }, function (reason) {
        if (done) return
        done = true
    })
    if (!done && res === IS_ERROR) {
        done = true
    }
}
class MyPromise {
    constructor(fn) {
        if (typeof fn !== 'function') {
            throw TypeError('Promise contructor\'s arguments is not a function')
        }
        if (fn === noop) return
        this._state = 0
        this._valule = null
        this._deferredState = 0
        this._deferreds = null
        doResolve(fn, this)
    }
}
复制代码

ES6中的类与函数声明的区别

  • 函数声明可以被提升,而类声明与let声明类似,不能被提升;真正执行声明语句之前,它们会一直存在于临时死区中
  • 类声明中的所有代码将自动运行在严格模式下,而且无法强行让代码脱离严格模式执行
  • 自定义类型中,需要通过Object.defineProperty()方法手工指定某个方法为不可枚举;而在类中,所有方法都是不可枚举的
  • 每个类都有一个名为[[Constructor]]的内部方法,通过关键字new调用那些不包含[[Constructor]]的方法会导致程序抛出错误
  • 使用除关键字new以外的方式调用类的构造函数会导致程序抛出错误
  • 在类中修改类名会导致程序报错

在es6的class类中,除了使用关键字new以外的方式调用类的构造函数都会报错,所以在MyPromise类中没有做this指向的判断

参考博客

源码速读!一看就会、一写就废的 Promise 实现

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享