写了一个有趣的 JS/TS 的任务管理库,可以帮助您中止异步函数/Promise 运行

4 天前
 pursuer

写过 JS 的都知道 JS/TS 的异步方案采用 async,await,Promise 的无栈协程方案。Python 也是采用的类似方案,但 Python 提供更多的控制包括 cancel 一个 task ,可以尝试提前结束一个异步任务,同时 JS/TS 也没有 current_task 或者类似 Java 的 ThreadLocal 获取上下文变量的方案。

通常的实现中断执行的写法是手动判断类似 AbortSignal.throwIfAborted 的方案,但写起来没那么舒心。

于是我想到是否可以通过改写 Promise.then 实现自动中断 await 执行?实际写下来以后的发现居然真的可以,于是有了下面的这个库。

https://github.com/partic2/protask

https://gitee.com/partic/protask

使用示例:


import {task} from 'protask'

function sleep<T>(milliSeconds: number, arg?: T): Promise<T> {
    return new Promise(function (resolve, reject) {
        setTimeout(resolve, milliSeconds, arg)
    });
}

async function printTaskLocal(){
    await sleep(100);
    console.info(task.locals());
}

task.create('test task 1',async ()=>{
    try{
        for(let i=0;i<100;i++){
            task.locals()!.count=i;
            await printTaskLocal();
            await sleep(1000)
        }
    }catch(e:any){
        console.info(e.toString());
    }
});

task.create('test task 2',(async ()=>{
    await sleep(3000);
    console.info('abort task 1')
    task.abort('test task 1');
}));

上面的代码创建了一个 task1 然后在 task2 中中断了 task1 的运行。同时在 task1 中打印 task local 。

目前只是一个非常简单实验性质的库,并未完善测试过,请注意使用风险。

觉得有意思的话可以点个 star ,万一以后就进 tc39 了呢?(笑

1242 次点击
所在节点    分享创造
24 条回复
pursuer
4 天前
@nomagick 浏览器上复现了你的问题,初步推断原因是 onfulfilled 后的代码被放到下一 tick 运行了,虽然可以简单通过移除
finally{task.currentTask='';}解决,但可能造成 task 泄露,我还得再看下
pursuer
4 天前
@nomagick 推了新版本解决了这个 BUG ,原来是我脑抽本地两份代码撤销的时候不一致了。

不过就像我前面说的,当前写法会导致 task 标记泄露污染不在 taskMain 里创建的 Promise ,不够完美。但目前想不到更好的办法了。
pursuer
4 天前
@nomagick 测试了下还真是,我发布的第一个有 BUG 的版本在被 tsc 编译为 yield 模拟 await 的代码里是正常运行的。使用原生 js 的 await 时,onfulfilled 的行为有点奇怪,不会立即运行 await 后面的代码。尝试 queueMicrotask 和 Promise.then 清除 currentTask 均不能按预期位置运行,唯一稍微可用方案是 setTimeout(0)但存在可能 4ms 限制且这个也不能确定执行时间点,只能在较大程度上缓解 currentTask 泄漏到其他 Promise 的问题。
1una0bserver
3 天前
@dapang1221 大前端不是早就搞成操作系统了吗🤔

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1081474

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX