JavaScript에서 비동기 작업을 취소하는 방법은 무엇입니까?

青灯夜游
풀어 주다: 2020-07-06 10:08:26
앞으로
2867명이 탐색했습니다.

JavaScript에서 비동기 작업을 취소하는 방법은 무엇입니까?

때로는 비동기 작업을 수행하는 것이 어려울 수 있습니다. 특히 특정 프로그래밍 언어가 실수로 시작되었거나 더 이상 필요하지 않은 작업의 취소를 허용하지 않는 경우에는 더욱 그렇습니다. 다행히 JavaScript는 비동기 활동을 중단하는 데 매우 편리한 기능을 제공합니다. 이 문서에서는 중단 가능한 함수를 만드는 방법을 배울 수 있습니다.

Abort 신호

ES2015에Promise가 도입되고 새로운 비동기 솔루션을 지원하기 위해 일부 웹 API가 등장한 직후비동기 작업을 취소해야 할 필요성이 나타났습니다Promise引入 ES2015 并出现了一些支持新异步解决方案的 Web API 之后不久,需要取消异步任务的需求就出现了。最初的尝试集中在创建通用解决方案上,并期待以后可以成为 ECMAScript 标准的一部分。但是,讨论很快陷入僵局,无法解决问题。因此,WHATWG 准备了自己的解决方案,并AbortController的形式将其直接引入 DOM。这种解决方案的明显缺点是 Node.js 中不提供AbortController,从而在该环境没有任何优雅或官方的方式来取消异步任务。

正如你在 DOM 规范中所看到的,AbortController是用一种非常通用的方式描述的。所以你可以在任何类型的异步 API 中使用 —— 甚至是那些目前还不存在的 API。目前只有 Fetch API 正式支持,但是你也可以在自己的代码中使用它!

在开始之前,让我们花点时间分析一下AbortController. 초기 시도는ECMAScript 표준 부분이 되기를 희망하면서 범용 솔루션을 만드는

에 중점을 둡니다. . 그러나 논의는 빠르게 교착상태에 빠졌고 문제를 해결하지 못했습니다. 따라서 WHATWG는 AbortController를 사용하여 자체 솔루션을 준비했습니다.는 이를 DOM

에 직접 소개합니다. 이 솔루션의 명백한 단점은 Node.js에서AbortController가 제공되지 않으므로 이 환경에서 비동기 작업을 취소하는 우아하거나 공식적인 방법이 없다는 것입니다.DOM 사양에서 볼 수 있듯이AbortController는 매우 일반적인 방식으로 설명됩니다. 따라서 아직 존재하지 않는 API라도 모든 종류의 비동기 API에서 사용할 수 있습니다. 현재는 Fetch API만 공식적으로 지원되지만, 자신의 코드에서도 사용할 수 있습니다!

시작하기 전에 잠시AbortController의 작동 방식을 분석해 보겠습니다.AbortControllerDOM 接口的新实例(1),并将其signal属性绑定到变量(2)。然后调用fetch()并传递signal作为其选项之一(3)。要中止获取资源,你只需调用abortController.abort()(4)。它将自动拒绝fetch()的 promise,并且控件将传递给catch()块(5)。

signal属性本身非常有趣,它是该节目的主要明星。该属性是AbortSignalDOM 接口的实例,该实例具有aborted属性,其中包含有关用户是否已调用abortController.abort()方法的信息。你还可以将abort事件侦听器绑定到将要调用abortController.abort()时调用的事件监听器。换句话说:AbortController只是AbortSignal

const abortController = new AbortController(); // 1 const abortSignal = abortController.signal; // 2 fetch( 'http://example.com', { signal: abortSignal // 3 } ).catch( ( { message } ) => { // 5 console.log( message ); } ); abortController.abort(); // 4
로그인 후 복사
위 코드를 보면 처음에 AbortController<가 생성된 것을 알 수 있습니다. /code> DOM 인터페이스의 새 인스턴스(1)이며 해당 signal속성을 변수(2)에 바인딩합니다. 그런 다음 fetch()를 호출하고 signal을 옵션 중 하나로 전달합니다(3). 리소스 검색을 중단하려면 abortController.abort()(4)를 호출하기만 하면 됩니다. 자동으로 fetch()약속을 거부하고 제어권이 catch()블록(5)으로 전달됩니다.

signal속성 자체는 꽤 흥미롭고 쇼의 주요 스타입니다. 이 속성은 AbortSignalDOM의 인스턴스입니다. 인터페이스

, 이 인스턴스에는 사용자가abortController.abort()메서드를 호출했는지 여부에 대한 정보가 포함된abort속성이 있습니다.abortController.abort()가 호출될 때 호출되는 이벤트 리스너에abort이벤트 리스너를 바인딩할 수도 있습니다. 즉,AbortControllerAbortSignal의 공개 인터페이스일 뿐입니다.

종료 가능 함수

매우 복잡한 계산을 수행하기 위해 비동기 함수를 사용한다고 가정해 보겠습니다(예:

대규모 배열의 데이터 처리 비동기식). 단순화를 위해 예제 함수는 결과를 반환하기 전에 5초를 기다려 이를 시뮬레이션합니다.
function calculate() { return new Promise( ( resolve, reject ) => { setTimeout( ()=> { resolve( 1 ); }, 5000 ); } ); } calculate().then( ( result ) => { console.log( result ); } );
로그인 후 복사
그러나 때때로 사용자는 비용이 많이 드는 이 작업을 중단할 수 있기를 원합니다. 네, 이런 능력이 있어야 합니다. 계산을 시작하고 중지하는 버튼을 추가하세요:

Calculate" title="" data-original-title="复制">

 
로그인 후 복사

在上面的代码中,向按钮(1)添加一个异步click事件侦听器,并在其中调用calculate()函数(2)。五秒钟后,将显示带有结果的警报对话框(3)。另外,script [type = module]用于强制 JavaScript 代码进入严格模式——因为它比'use strict'编译指示更为优雅。

现在添加中止异步任务的功能:

{ // 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)。

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

const abortController = new AbortController(); abortController.abort(); calculate( abortController.signal );
로그인 후 복사

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

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에서 비동기 작업을 취소하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:segmentfault.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!