Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Rejecting with a promise is not fully tested #59

@ziriax

Description

@ziriax

For learning promises, I made my own little implementation, see code below. I'm a Javascript newbie, so Douglas, don't be too hard on me please ;-)

For simplicity, it uses process.nextTick, so it only works in nodejs for now.

However, all 872 specs of your test suite pass, whether or not I 'adopt the state' of a 'thenable' passed as an argument to the reject method. See the single comment in the code.

What is the correct behavior?

Thanks a lot,
Peter Verswyvelen

var deferred = (function() {

    function Deferred() {
        this.promise = {
            then: this.then.bind(this),
        };
        this.thens = [];
    }

    function call_thens(state, value, thens) {
        thens.forEach(function (then) {
            var cfn = then[state],
                next_value = value,
                next_state = state;
            if (typeof cfn === "function") {
                try {
                    next_value = cfn(value);
                    next_state = "done";
                } catch (error) {
                    next_value = error;
                    next_state = "fail";
                }
            }

            then.next.transit(next_state, next_value);
        });
    }

    function then_transit(id, state, value) {
        if (this.state === id) {
            delete this.state;
            this.transit(state, value);
        }
    }

    var next_then_id = 0;

    Deferred.prototype = {
        asap: function () {
            process.nextTick(call_thens.bind(
                     this, this.state, this.value, this.thens));
            this.thens = [];
        },

        switchTo: function(state, value) {
            this.value = value;
            this.state = state;
            this.asap();
        },

        transit: function (state, value) {
            if (typeof this.state === "undefined") {
                // All tests succeeds with or without the state === "done" check?
                if (state === "done" && 
                     (typeof value === "function" || 
                         (typeof value === "object" && value !== null))) {
                    try {
                        if (value === this.promise)
                            throw new TypeError();

                        var then = value.then;
                        if (typeof then === "function") {
                            this.promise.then = then.bind(value);
                            var id = this.state = ++next_then_id;
                            try {
                                then.call(value,
                                    then_transit.bind(this, id, "done"),
                                    then_transit.bind(this, id, "fail"));
                            } catch (error) {
                                if (this.state === id)
                                    this.switchTo("fail", error);
                            } finally {
                                return;
                            }
                        }
                    } catch (error) {
                        value = error;
                        state = "fail";
                    }
                }

                this.switchTo(state, value);
            }
        },

        resolve: function (value) {
            this.transit("done", value);
        },

        reject: function (value) {
            this.transit("fail", value);
        },

        then: function (done, fail) {
            var then = {
                next: new Deferred(),
                done: done,
                fail: fail
            }

            this.thens.push(then);

            if (this.state)
                this.asap();

            return then.next.promise;
        }
    }

    return function () {
        return new Deferred();
    }
})();

var promisesAplusTests = require("promises-aplus-tests");

promisesAplusTests({
    deferred: deferred
}, {
    reporter: "spec"
});

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions