Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promise #17

Open
wweggplant opened this issue Sep 25, 2023 · 0 comments
Open

Promise #17

wweggplant opened this issue Sep 25, 2023 · 0 comments

Comments

@wweggplant
Copy link
Owner

wweggplant commented Sep 25, 2023

标准

通过阅读Promises/A+规范发现,该规范明确强调了不会说明Promise是如何createfulfillreject的, 仅仅是提供then方法的操作. 其中的内容大部分围绕then方法,甚至也可以说Promises/A+规范就是关于then的操作手册.也就是说, 标准并没有规定我们常用的catchall等方法.

三种状态

  1. 初始状态为pending, 该状态可以转变成其他两种状态
  2. fulfilled状态下有一个不可变更的值
  3. rejected状态下有一个不可变更的原因

ps.不可变更的意思是===

then方法

promise提供的then方法, 在这个方法中有两个参数onFulfilled、onRejected,这两个参数是非必填的.

    promise.then(onFulfilled, onRejected)

onFulfilled, onRejected的判断过程

  1. onFulfilledonRejectedoptional参数,如果是非函数的,则会忽略掉.
  2. onFulfilled函数:
    1. 必须在promise处于fulfilled状态后才可以调用

实战

  1. 尝试翻译总结Promise A+的标砖
  2. 跟着剖析Promise内部结构,一步一步实现一个完整的、能通过所有Test case的Promise类这篇文章实现了自己的Promise类
  3. axios里的平常经常用的拦截器,本质上就是一串 promise 的串行执行。
  // Hook up interceptors middleware
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(config);

  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }
try {
  module.exports = Promise
} catch (e) {}

function Promise(executor) {
    var self = this
    self.data = undefined
    self.status = 'pending'
    self.onResolvedCallbacks = []
    self.onRejectedCallbacks = []
    function resolve(value) {
        if (value instanceof Promise) {
            return value.then(resolve, reject)
        }
        setTimeout(function() {
            if (self.status === 'pending'){
                self.data = value
                self.status = 'resolved'
                for (var i = 0; i < self.onResolvedCallbacks.length; i++) {
                    self.onResolvedCallbacks[i](self.data)
                }
            }
        }, 0);
    }
    function reject(reason) {
        setTimeout(function() {
            if (self.status === 'pending'){
                self.data = reason
                self.status = 'rejected'
                for (var i = 0; i < self.onRejectedCallbacks.length; i++) {
                    self.onRejectedCallbacks[i](reason)
                }
            }
        }, 0);
    }
    try {
        executor(resolve, reject)
    } catch (error) {
        reject(error)
    }
}
function promiseResolvle(promise2, x, resolve, reject) {
    if (promise2 === x) {
        return reject(new TypeError('Chaining cycle detected for promise!'))
    }
    var then;
    var isCallThenOrCatch = false;
    if (x instanceof Promise) {
        // 2.3.2
        if (x.status === 'pending'){
            x.then(function(y){
                promiseResolvle(promise2, y, resolve, reject)
            }, reject)
        } else {
            x.then(resolve, reject)
        }
    } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        try {
            then = x.then
            if (typeof then === 'function'){
                then.call(x, function (y) {
                    if (isCallThenOrCatch) return
                    isCallThenOrCatch = true
                    promiseResolvle(promise2, y, resolve, reject)
                }, function (r) {
                    if (isCallThenOrCatch) return
                    isCallThenOrCatch = true
                    reject(r)
                })
            } else {
                resolve(x)
            }
        } catch (error) {
            if (isCallThenOrCatch) return
            isCallThenOrCatch = true
            reject(error)
        }
    } else {
        resolve(x)
    }
}
Promise.prototype.then = function(onFulfilled, onRejected) {
    var self = this
    var promise2;
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) {return value}
    onRejected = typeof onRejected === 'function' ? onRejected : function (reason) { throw reason }
    if (self.status === 'resolved'){
        return promise2 = new Promise(function (resolve, reject) {
            setTimeout(function() {
                try {
                    var x = onFulfilled(self.data)
                    promiseResolvle(promise2, x, resolve, reject);
                } catch (error) {
                    reject(error)
                }
            }, 0);
        })
    }
    if (self.status === 'rejected'){
        return promise2 = new Promise(function (resolve, reject) {
            setTimeout(function() {
                try {
                    var x = onRejected(self.data)
                    promiseResolvle(promise2, x, resolve, reject);
                } catch (error) {
                    reject(error)
                }
            }, 0);
        })
    }
    if (self.status === 'pending'){
        return promise2 = new Promise(function (resolve, reject) {
            self.onResolvedCallbacks.push(function (value) {
                try {
                    var x = onFulfilled(value)
                    promiseResolvle(promise2, x, resolve, reject);
                } catch (error) {
                    reject(error)
                }
            })
            self.onRejectedCallbacks.push(function (reason) {
                try {
                    var x = onRejected(reason)
                    promiseResolvle(promise2, x, resolve, reject);
                } catch (error) {
                    reject(error)
                }
            })
        })
    }
}

Promise.prototype.catch = function(onRejected) {
  return this.then(null, onRejected)
}

Promise.deferred = Promise.defer = function() {
  var dfd = {}
  dfd.promise = new Promise(function(resolve, reject) {
    dfd.resolve = resolve
    dfd.reject = reject
  })
  return dfd
}

参考

  1. Promise A+ 英文文档
  2. 剖析Promise内部结构,一步一步实现一个完整的、能通过所有Test case的Promise类
  3. 最简实现Promise,支持异步链式调用(20行)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant