我是否继承了Promise类并以这种方式正确使用它?

时间:2018-02-06 19:37:37

标签: javascript

我的背景是C#。所以,当我来到Javascript时,我想根据语法使它与C#保持友好。所以,我正在写这个小插件:



(function (global) {
    'use strict';

    //require('babel-polyfill');
    
    let Task = (function () {
        let __task__ = Symbol('Task'),
            __data = {};

        __data.then = function (...args) {
            if (args.length) {
                let run = this[__task__]['run'];

                this[__task__]['TResult'] = run();

                return Promise.resolve(this[__task__]['action']).then(args[0], args[1]);
            }
        };   
        __data.Run = function (...args) {
            if (args.length) {
                let func = args[0];

                return new Task(func);
            }
        };
        __data.Wait = function (...args) {
            let run = this[__task__]['run'];

            this[__task__]['TResult'] = run();

            return this;
        };
        
        class Task extends Promise {
            constructor(action) {
                let run = null;

                super((resolve, reject) => run = () => action(resolve, reject));

                this[__task__] = {
                    action: action,
                    run: run
                };
            }
            set then(value) {
                return __data.then;
            }
            get then() {
                return (...args) => __data.then.call(this, ...args);
            }
            set Result(result) {
                return this[__task__]['TResult'] || undefined;
            }
            get Result() {
                return this[__task__]['TResult'] || undefined;
            }
            static set Run(value) {
                return __data.Run;
            }
            static get Run() {
                return (...args) => __data.Run.call(this, ...args);
            }
            set Wait(value) {
                return __data.Wait;
            }
            get Wait() {
                return (...args) => __data.Wait.call(this, ...args);
            }
        }
        return Task;
    }());

    //module.exports = Task;
    global.Task = Task;
}(typeof window !== 'undefined' ? window : this));

(async () => {
    let $log = window.$log || console.log;

    let func = function () {
        $log('foo');

        return 'bar';
    };

    let task = Task.Run(() => func());

    for (let i of [1, 2, 3]) {
        $log(`start... [${i}]`);

        await task;

        $log('result:', task.Result);

        $log('done.');

        $log('==========');
    }

    $log('using "Wait" method:');

    task = Task.Run(() => func());

    $log('start...');

    task.Wait();

    $log('result:', task.Result);
    $log('done.');
})();




让我先对它们进行比较:

C#语法:

    static Task<string> func()
    {
        Console.WriteLine("foo");

        return Task.FromResult<string>("bar");
    }

    static async Task Main()
    {
        Task<string> task = Task.Run(() => func());

        foreach (int i in new int[3] { 1, 2, 3 })
        {
            Console.WriteLine($"start...[{i}]");

            await task;

            Console.WriteLine($"Result: {task.Result}");
            Console.WriteLine("done.");
            Console.WriteLine("==========");
        }

        Console.WriteLine("using \"Wait\" method:");

        task = Task.Run(() => func());

        Console.WriteLine("start...");

        task.Wait();

        Console.WriteLine($"Result: {task.Result}");
        Console.WriteLine("done.");
    }

JS语法:

(async () => {
    let $log = window.$log || console.log;

    let func = function () {
        $log('foo');

        return 'bar';
    };

    let task = Task.Run(() => func());

    for (let i of [1, 2, 3]) {
        $log('start...');

        await task;

        $log('result:', task.Result);

        $log('done.');

        $log('==========');
    }

    $log('using "Wait" method:');

    task = Task.Run(() => func());

    $log('start...');

    task.Wait();

    $log('result:', task.Result);
    $log('done.');
})();

使这个插件工作的要点是:

constructor(action) {
    let run = null;

    super((resolve, reject) => run = () => action(resolve, reject));

    this[__task__] = {
        action: action,
        run: run
    };
}

__data.then = function (...args) {
    if (args.length) {
        let run = this[__task__]['run'];

        this[__task__]['TResult'] = run();

        return Promise.resolve(this[__task__]['action']).then(args[0], args[1]);
    }
};

我已使用run作为变量来存储承诺的内容,并在每次await次调用时使用它。

与我在Google上搜索extends promise的另一个例子有所不同:

class AngularPromise extends Promise {
    constructor(executor) {
        super((resolve, reject) => {
            // before
            return executor(resolve, reject);
        });
        // after
    }

    then(onFulfilled, onRejected) {
        // before
        const returnValue = super.then(onFulfilled, onRejected);
        // after
        return returnValue;
    }
}

它包含以下问题:

1 /。它在await调用之前运行promise中的代码。

$log('start...');

await task;

输出:

  

foo

     

...启动

2 /。它不能与await多次一起使用

await task; // works
await task; // does nothing
await task; // does nothing

$log('done.'); // never logged

3 /。它需要首先运行promise的内容,否则抛出错误消息:

  

承诺解析或拒绝功能不可调用

super((resolve, reject) => {
    // this line would run the function
    // so, what's happened if I store it to "run"
    // and return a fake function?

    return executor(resolve, reject);
});

试验:

let run;

super((resolve, reject) => {
    run = () => executor(resolve, reject);

    let foo = function () { };

    return foo(resolve, reject);
});

this.run = run;

then(onFulfilled, onRejected) {
    this.run(); // works

    // Promise resolve or reject function is not callable
    const returnValue = super.then(onFulfilled, onRejected);

    return returnValue;
}

另一点,我认为这不是一种正确的使用方法。但它应该有很多帮助:

then方法中:

return Promise.resolve(this[__task__]['action']).then(args[0], args[1]);

同样:

return Promise.resolve(func).then(onFulfilled, onRejected);

我需要的一切是:

我需要一个返回值,值是一个promise。此外,promise包含一个函数,只包含,不运行它。

所以,如果我将Promise.resolve更改为:

// "new Promise" runs the function...
return new Promise(func).then(onFulfilled, onRejected);

// infinite loop...
return new Task(func).then(onFulfilled, onRejected);

它的工作错误。

添加点:在C#中,没有resolvereject的概念。所以,我想我可以破解一下代码。

这意味着:Promise.resolve并不代表it's always resolved

你对此有任何想法吗?

p / s:我花了很多时间才完成,请不要在没有评论的情况下结束。谢谢!

0 个答案:

没有答案