如何取消JavaScript中的异步任务?


当前第2页 返回上一页

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

{ // 1

  let abortController = null; // 2

 

document.querySelector('#calculate').addEventListener('click',async ( { target } )=>{

    if ( abortController ) {

      abortController.abort(); // 5

 

      abortController = null;

      target.innerText = 'Calculate';

 

      return;

    }

 

    abortController = new AbortController(); // 3

    target.innerText = 'Stop calculation';

 

    try {

      const result = await calculate( abortController.signal ); // 4

 

      alert( result );

    } catch {

      alert( 'WHY DID YOU DO THAT?!' ); // 9

    } finally { // 10

      abortController = null;

      target.innerText = 'Calculate';

    }

  } );

 

  function calculate( abortSignal ) {

    return new Promise( ( resolve, reject ) => {

      const timeout = setTimeout( ()=> {

        resolve( 1 );

      }, 5000 );

 

      abortSignal.addEventListener( 'abort', () => { // 6

        const error = new DOMException(

         'Calculation aborted by the user', 'AbortError'

         );

 

        clearTimeout( timeout ); // 7

        reject( error ); // 8

      } );

    } );

  }

}

如你所见,代码变得更长了。但是没有理由惊慌,它并没有变得更难理解!

一切都包含在块(1)中,该块相当于IIFE。因此,abortController 变量(2)不会泄漏到全局作用域内。

首先,将其值设置为 null 。鼠标单击按钮时,此值会更改。然后将其值设置为 AbortController 的新实例(3)。之后,将实例的 signal 属性直接传递给你的 calculate() 函数(4)。

如果用户在五秒钟之内再次单击该按钮,则将导致调用 abortController.abort() 函数(5)。反过来,这将在你先前传递给 calculate()AbortSignal 实例上触发 abort 事件(6)。

abort 事件侦听器内部,删除了滴答计时器(7)并拒绝了带有适当错误的promise (8; 根据规范 ,它必须是类型为 'AbortError'DOMException)。该错误最终把控制权传递给 catch(9)和 finally 块(10)。

你还应该准备处理如下情况的代码:

1

2

3

4

const abortController = new AbortController();

 

abortController.abort();

calculate( abortController.signal );

在这种情况下,abort 事件将不会被触发,因为它发生在将信号传递给 calculate() 函数之前。因此你应该进行一些重构:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

function calculate( abortSignal ) {

  return new Promise( ( resolve, reject ) => {

    const error = new DOMException(

    'Calculation aborted by the user', 'AbortError'

    ); // 1

 

    if ( abortSignal.aborted ) { // 2

      return reject( error );

    }

 

    const timeout = setTimeout( ()=> {

      resolve( 1 );

    }, 5000 );

 

    abortSignal.addEventListener( 'abort', () => {

      clearTimeout( timeout );

      reject( error );

    } );

  } );

}

错误被移到顶部(1)。因此,你可以在代码不同部分中重用它(但是,创建一个错误工厂会更优雅,尽管听起来很愚蠢)。另外出现了一个保护子句,检查 abortSignal.aborted(2)的值。如果等于 true,那么 calculate() 函数将会拒绝带有适当错误的 promise,而无需执行任何其他操作。

这就是创建完全可中止的异步函数的方式。 演示可在这里获得(https://blog.comandeer.pl/ass...)。请享用!

英文原文地址:https://ckeditor.com/blog/Aborting-a-signal-how-to-cancel-an-asynchronous-task-in-JavaScript/

相关教程推荐:JavaScript视频教程

以上就是如何取消JavaScript中的异步任务?的详细内容,更多文章请关注木庄网络博客

返回前面的内容

相关阅读 >>

javascript中的垃圾回收和内存泄漏

什么是javascript引擎

javascript是一门什么脚本语言

typescript和javascript有什么区别

js怎样直接操作二进制数据

javascript怎么改变文本内容

介绍javascript正则实现表达式以字母开头

jscript和javascript的区别是什么

javascript如何定义方法

聊聊typescript中enum(枚举)的用法

更多相关阅读请进入《javascript》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...