我的背景是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#中,没有resolve
或reject
的概念。所以,我想我可以破解一下代码。
这意味着:Promise.resolve
并不代表it's always resolved
。
你对此有任何想法吗?
p / s:我花了很多时间才完成,请不要在没有评论的情况下结束。谢谢!