Skip to content

关于promise/A+的几个疑问? #16

Description

@zhufengnodejs

一种实现代码

function Promise(executor) {
    let self = this;
    self.status = 'pending';
    self.value = undefined;
    self.onResolvedCallbacks = [];
    self.onRejectedCallbacks = [];

    function resolve(value) {
        if (value instanceof Promise)
            return value.then(resolve, reject);

        setTimeout(function () {
            if (self.status == 'pending') {
                self.status = 'fulfilled';
                self.value = value;
                self.onResolvedCallbacks.forEach(item => item(value));
            }
        });
    }

    function reject(reason) {
        setTimeout(function () {
            if (self.status == 'pending') {
                self.status = 'rejected';
                self.value = reason;
                self.onRejectedCallbacks.forEach(item => item(reason));
            }
        });
    }

    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

function resolvePromise(promise2, x, resolve, reject) {
    if (x === promise2)
        return reject(new TypeError('死循环'));
    let then, called = false;
    if (x instanceof Promise) {
        if (x.status == "pending") {
            x.then(function (y) {
                resolvePromise(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 (called) return;
                    called = true;
                    resolvePromise(promise2, y, resolve, reject);
                }, function (y) {
                    if (called) return;
                    called = true;
                    reject(y);
                });
            }else{
                resolve(x);
            }
        } catch (e) {
            if (called) return;
            called = true;
            reject(e);
        }
    } else {
        resolve(x);
    }
}

Promise.prototype.then = function (onFulfilled, onRejected) {
    let self = this;
    var promise2;
    onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected == 'function' ? onRejected : reason => {
        throw reason
    };
    if (self.status == 'fulfilled') {
        return promise2 = new Promise(function (resolve, reject) {
            setTimeout(function() {
                try {
                    let x = onFulfilled(self.value);
                    resolvePromise(promise2, x, resolve, reject)
                } catch (e) {
                    reject(e);
                }
            });
        });
    }
    if (self.status == 'rejected') {
        return promise2 = new Promise(function (resolve, reject) {
            setTimeout(function() {
                try {
                    let x = onRejected(self.value);
                    resolvePromise(promise2, x, resolve, reject)
                } catch (e) {
                    reject(e);
                }
            });
        });
    }
    if (self.status == 'pending') {
        return promise2 = new Promise(function (resolve, reject) {
            self.onResolvedCallbacks.push(function () {
                try {
                    let x = onFulfilled(self.value);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            });
            self.onRejectedCallbacks.push(function () {
                try {
                    let x = onRejected(self.value);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            });
        });
    }
}

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
}

module.exports = Promise;

我有以下问题

  1. x === promise2什么时候会出现?为什么会循环依赖?
  2. 添加called是为了防止多次then,什么时候出现这种情况?
  3. 为什么要在处理函数里用setTimeout?
  4. typeof x == 'function' 什么时候x会是一个对象

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions