如何优雅地取消 JavaScript 异步任务_javascript技巧

来源:脚本之家  责任编辑:小易  

使用ajax就可以使用异步加载。推荐使用jquery实现异步加载。使用原生js开发速度会下降很多。

在程序中处理异步任务通常比较麻烦,尤其是那些不支持取消异步任务的编程语言。所幸的是,JavaScript 提供了一种非常方便的机制来取消异步任务。

异步完成后调用函数

中断信号

自从 ES2015 引入了  Promise ,开发者有了取消异步任务的需求,随后推出的一些 Web API 也开始支持异步方案,比如 Fetch API。TC39 委员会(就是制定 ECMAScript 标准的组织)最初尝试定义一套通用的解决方案,以便后续作为 ECMAScript 标准。但是后来讨论不出什么结果来,这个问题也就搁置了。鉴于此,WHATWG (HTML 标准制定组织)另起炉灶,自己搞出一套解决方案,直接在 DOM 标准上引入了 AbortController。这种做法的坏处显而易见,因为它不是语言层面的 ECMAScript 标准,因此 Node.js 平台也就不支持  AbortController 

方法一:也叫Script DOM Element方法二:onload时的异步加载方法三:其他方法

在 DOM  规范里, AbortController 设计得非常通用,因此事实上你可以用在任何异步 API 中。目前只得到 Fetch API 的官方支持,但你完全可以用在自己的异步代码里。

js能异步是因为它用能调用的模块是异步的。js都是单线程的。而且只有一个事件队列(也可以理解成任务

在开始介绍之前,我们先看下 AbortController 的工作原理:

function async () {}setTimeout(function(){ asyn

还是比较中意华为,小米的营销动作真的越来越花哨了。两者的商业模式不一样,一个追求硬件利润,一个做价格厚道感动人心的产品,追求用户数量,靠互联网思维赚钱,本质上都是赚钱为目的。但是区别是小米手机一直定位性价比,给人一种屌丝机的印象,华为从杨柘负责营销之后,把华为品牌形象由工科男直接拉升到文艺范,成功建立了高端形象,加上商务设计和渠道返利的加持,以及华为手机不低的品质,所以收割了一大片粉丝。从小米6定价2499到小米亮银版拍出近10万的天价,就可以知道小米想要冲击高端机的野心,在目前国人的思维模式下,估计不会很受待见。毕竟当时小米在市场上杀出一条血路靠得就是性价比三个字啊,而且越来越多的冠名活动,

const abortController = new AbortController(); // 1 const abortSignal = abortController.signal; // 2 fetch( 'http://kaysonli.com', { signal: abortSignal // 3 } ).catch( ( { message } ) => { // 5 console.log( message ); } ); abortController.abort(); // 4

感谢头条的邀请。不管怎么说,对这位妈妈描述的情况,还真的感觉到比较难以解决。而我个人认为,不管怎么样一家人在一起是最好的选择。不过很多事情是很难,十全十美的,从这位妈妈描述的情况来分析,爸爸工作的地方,应该离家不是很远,因为最初的计划是妈妈计划每半个月往返一次吗?所以说按我的想法,就是妈妈在家陪伴着两个孩子,然后爸爸能够半个月,定期回来看望妻子儿女一次,利用这一次团聚,好好享受家庭时光,这样的安排,我认为要比最初的想法好上很多,因为在那样的情况下孩子既看不到爸爸,也看不到妈妈,而且两个孩子还分开了,丝毫没有家庭的概念。我对这位妈妈说的是有孩子就要有所付出,而不能够怨天尤人,而真正享受和孩子在一

上面的代码很简单,首先创建了AbortController的一个实例(1),并将它的 signal 属性赋值给一个变量(2)。然后调用fetch()并传入 signal 参数(3)。取消请求时调用 abortController.abort()(4)。这样就会自动执行fetch() 的 reject ,也就是进入catch()部分(5)。

首先回顾下整个事件6月20日下午,龙某意外被狗咬伤,大家都以为只要及时注射狂犬疫苗就可以,没想到,事情的发展让人难以接受。龙某丈夫马洪周说,6月20日下午5时许,龙某去西稍门十字附近的一家饭店看货,饭店在十字北100米路东,她从路西过马路,在马路中间,被一条狗咬了,“她当晚回去说,狗和她迎面都走过了,狗又转过身来咬她,左腿外踝和内踝都被咬伤。”龙某给家人说过,那是条长约60公分的狗,类似于哈巴狗,没人牵。当时着急着去打针,也没有顾上其他的。随后,龙某前往西安市中心医院急诊科治疗,被诊断为左踝狗咬伤,并及时注射了狂犬疫苗。此后,龙某按照医嘱,又注射了3针狂犬疫苗,但到了7月13日,她感觉左腿发麻

它的signal属性是核心所在。该属性是 AbortSignal DOM 接口的实例,它有一个 aborted属性,带有是否调用了 abortController.abort()的相关信息。还可以在上面监听abort事件,该事件在abortController.abort()调用时触发。简单来说,AbortController 就是AbortSignal的一个公开接口。

整个时尚圈都在穿小白鞋,相信很多人都有一双StanSmith或Superstar,便宜百搭又时髦。不过,你的StanSmith和Superstar也许很快就要过时了,因为最近很多球鞋回潮正当时。NikeCortez阿甘鞋首先要说的就是因《阿甘正传》而闻名的NikeCortez阿甘鞋。今年品牌代言人BellaHadid重新演绎了NikeCortez大片,这双鞋大有当年stansmith的样子。身为代言人把很多个颜色都穿了个遍,但也看得出来这双鞋搭配运动装、连衣裙或是连体裤都时髦得毫无压力。周冬雨和郑秀妍Jessica也很爱穿匡威converse在小白鞋走红之前,其实Converse也曾几何时被称

可取消的函数

假设有一个执行复杂计算的异步函数,为简单起见,我们就用定时器模拟:

还是比较中意华为,小米的营销动作真的越来越花哨了。两者的商业模式不一样,一个追求硬件利润,一个做价格厚道感动人心的产品,追求用户数量,靠互联网思维赚钱,本质上都是赚钱为目的。但是区别是小米手机一直定位性价比,给人一种屌丝机的印象,华为从杨柘负责营销之后,把华为品牌形象由工科男直接拉升到文艺范,成功建立了高端形象,加上商务设计和渠道返利的加持,以及华为手机不低的品质,所以收割了一大片粉丝。从小米6定价2499到小米亮银版拍出近10万的天价,就可以知道小米想要冲击高端机的野心,在目前国人的思维模式下,估计不会很受待见。毕竟当时小米在市场上杀出一条血路靠得就是性价比三个字啊,而且越来越多的冠名活动,

function calculate() { return new Promise( ( resolve, reject ) => { setTimeout( ()=> { resolve( 1 ); }, 5000 ); } ); } calculate().then( ( result ) => { console.log( result ); } );

可能的情况是,用户想取消这种耗时的任务。我们用一个按钮来开始和停止:

还是比较中意华为,小米的营销动作真的越来越花哨了。两者的商业模式不一样,一个追求硬件利润,一个做价格厚道感动人心的产品,追求用户数量,靠互联网思维赚钱,本质上都是赚钱为目的。但是区别是小米手机一直定位性价比,给人一种屌丝机的印象,华为从杨柘负责营销之后,把华为品牌形象由工科男直接拉升到文艺范,成功建立了高端形象,加上商务设计和渠道返利的加持,以及华为手机不低的品质,所以收割了一大片粉丝。从小米6定价2499到小米亮银版拍出近10万的天价,就可以知道小米想要冲击高端机的野心,在目前国人的思维模式下,估计不会很受待见。毕竟当时小米在市场上杀出一条血路靠得就是性价比三个字啊,而且越来越多的冠名活动,

<button id="calculate">Calculate</button> <script type="module"> document.querySelector( '#calculate' ).addEventListener( 'click', async ( { target } ) => { // 1 target.innerText = 'Stop calculation'; const result = await calculate(); // 2 alert( result ); // 3 target.innerText = 'Calculate'; } ); function calculate() { return new Promise( ( resolve, reject ) => { setTimeout( ()=> { resolve( 1 ); }, 5000 ); } ); } </script>

上面的代码给按钮绑定了一个异步的 click 事件处理器(1),并在里面调用了 calculate() 函数(2)。5 秒后会弹出对话框显示结果(3)。顺便提一下,script[type=module]可以让 JavaScript 代码进入严格模式,跟 'use strict' 的效果一样。

增加中断异步任务的功能:

还是比较中意华为,小米的营销动作真的越来越花哨了。两者的商业模式不一样,一个追求硬件利润,一个做价格厚道感动人心的产品,追求用户数量,靠互联网思维赚钱,本质上都是赚钱为目的。但是区别是小米手机一直定位性价比,给人一种屌丝机的印象,华为从杨柘负责营销之后,把华为品牌形象由工科男直接拉升到文艺范,成功建立了高端形象,加上商务设计和渠道返利的加持,以及华为手机不低的品质,所以收割了一大片粉丝。从小米6定价2499到小米亮银版拍出近10万的天价,就可以知道小米想要冲击高端机的野心,在目前国人的思维模式下,估计不会很受待见。毕竟当时小米在市场上杀出一条血路靠得就是性价比三个字啊,而且越来越多的冠名活动,

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

如果用户在 5 秒之内再次点击按钮,就会执行abortController.abort()函数(5)。这样就会在刚才传给 calculate()的AbortSignal实例上触发 abort 事件(6)。

在 abort 事件处理器里面清除定时器(7),然后用一个适当的异常对象拒绝 Promise(8)。

根据 DOM 规范,这个异常对象必须是一个'AbortError' 类型的DOMException

这个异常对象最终传给了catch (9) 和finally (10)。

但是还要考虑这样一种情况:

还是比较中意华为,小米的营销动作真的越来越花哨了。两者的商业模式不一样,一个追求硬件利润,一个做价格厚道感动人心的产品,追求用户数量,靠互联网思维赚钱,本质上都是赚钱为目的。但是区别是小米手机一直定位性价比,给人一种屌丝机的印象,华为从杨柘负责营销之后,把华为品牌形象由工科男直接拉升到文艺范,成功建立了高端形象,加上商务设计和渠道返利的加持,以及华为手机不低的品质,所以收割了一大片粉丝。从小米6定价2499到小米亮银版拍出近10万的天价,就可以知道小米想要冲击高端机的野心,在目前国人的思维模式下,估计不会很受待见。毕竟当时小米在市场上杀出一条血路靠得就是性价比三个字啊,而且越来越多的冠名活动,

const abortController = new AbortController(); abortController.abort(); calculate( abortController.signal );

这种情况下 abort 事件不会触发,因为它在signal传给calculate() 函数前就执行了。为此我们需要改造下代码:

还是比较中意华为,小米的营销动作真的越来越花哨了。两者的商业模式不一样,一个追求硬件利润,一个做价格厚道感动人心的产品,追求用户数量,靠互联网思维赚钱,本质上都是赚钱为目的。但是区别是小米手机一直定位性价比,给人一种屌丝机的印象,华为从杨柘负责营销之后,把华为品牌形象由工科男直接拉升到文艺范,成功建立了高端形象,加上商务设计和渠道返利的加持,以及华为手机不低的品质,所以收割了一大片粉丝。从小米6定价2499到小米亮银版拍出近10万的天价,就可以知道小米想要冲击高端机的野心,在目前国人的思维模式下,估计不会很受待见。毕竟当时小米在市场上杀出一条血路靠得就是性价比三个字啊,而且越来越多的冠名活动,

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,没必要再往下执行了。

到这里我们就实现了一个完整的可取消的异步函数,以后碰到需要处理异步任务的地方就可以派上用场了。

到此这篇关于如何优雅地取消 JavaScript 异步任务的文章就介绍到这了,更多相关JavaScript 取消异步任务内容请搜索真格学网以前的文章或继续浏览下面的相关文章希望大家以后多多支持真格学网!

扩展阅读,根据您访问的内容系统为您准备了以下内容,希望对您有帮助。

如何优雅地写js异步代码

用jquery

$.ajax({

   type : "post",//请求方式

   url : url,//请求地址

   dateType : "json",

   data:{'参数1':值1 ...},//请求参数

   success : function(data) { 

      

   }

});

javascript中异步操作的异常怎么处理

一、JavaScript异步编程的两个核心难点

异步I/O、事件驱动使得单线程的JavaScript得以在不阻塞UI的情况下执行网络、文件访问功能,且使之在后端实现了较高的性能。然而异步风格也引来了一些麻烦,其中比较核心的问题是:

1、函数嵌套过深

JavaScript的异步调用基于回调函数,当多个异步事务多级依赖时,回调函数会形成多级的嵌套,代码变成

金字塔型结构。这不仅使得代码变难看难懂,更使得调试、重构的过程充满风险。

2、异常处理

回调嵌套不仅仅是使代码变得杂乱,也使得错误处理更复杂。这里主要讲讲异常处理。

二、异常处理

像很多时髦的语言一样,JavaScript 也允许抛出异常,随后再用一个try/catch

语句块捕获。如果抛出的异常未被捕获,大多数JavaScript环境都会提供一个有用的堆栈轨迹。举个例子,下面这段代码由于'{'为无效JSON

对象而抛出异常。

?

12345678

function JSONToObject(jsonStr) { return JSON.parse(jsonStr);}var obj = JSONToObject('{');//SyntaxError: Unexpected end of input//at Object.parse (native)//at JSONToObject (/AsyncJS/stackTrace.js:2:15)//at Object.<anonymous> (/AsyncJS/stackTrace.js:4:11)

堆栈轨迹不仅告诉我们哪里抛出了错误,而且说明了最初出错的地方:第4 行代码。遗憾的是,自顶向下地跟踪异步错误起源并不都这么直截了当。

异步编程中可能抛出错误的情况有两种:回调函数错误、异步函数错误。

1、回调函数错误

如果从异步回调中抛出错误,会发生什么事?让我们先来做个测试。

?

1234567

setTimeout(function A() { setTimeout(function B() { setTimeout(function C() { throw new Error('Something terrible has happened!'); }, 0); }, 0);}, 0);

上述应用的结果是一条极其简短的堆栈轨迹。

?

12

Error: Something terrible has happened!at Timer.C (/AsyncJS/nestedErrors.js:4:13)

等等,A 和B 发生了什么事?为什么它们没有出现在堆栈轨迹中?这是因为运行C 的时候,异步函数的上下文已经不存在了,A 和B 并不在内存堆栈里。这3

个函数都是从事件队列直接运行的。基于同样的理由,利用try/catch

语句块并不能捕获从异步回调中抛出的错误。另外回调函数中的return也失去了意义。

?

1234567

try { setTimeout(function() { throw new Error('Catch me if you can!'); }, 0);} catch (e) {console.error(e);}

看到这里的问题了吗?这里的try/catch 语句块只捕获setTimeout函数自身内部发生的那些错误。因为setTimeout

异步地运行其回调,所以即使延时设置为0,回调抛出的错误也会直接流向应用程序。

总的来说,取用异步回调的函数即使包装上try/catch 语句块,也只是无用之举。(特例是,该异步函数确实是在同步地做某些事且容易出错。例如,Node

的fs.watch(file,callback)就是这样一个函数,它在目标文件不存在时会抛出一个错误。)正因为此,Node.js

中的回调几乎总是接受一个错误作为其首个参数,这样就允许回调自己来决定如何处理这个错误。

2、异步函数错误

由于异步函数是立刻返回的,异步事务中发生的错误是无法通过try-catch来捕捉的,只能采用由调用方提供错误处理回调的方案来解决。

例如Node中常见的function (err, ...)

{...}回调函数,就是Node中处理错误的约定:即将错误作为回调函数的第一个实参返回。再比如HTML5中FileReader对象的onerror函数,会被用于处理异步读取文件过程中的错误。

举个例子,下面这个Node 应用尝试异步地读取一个文件,还负责记录下任何错误(如“文件不存在”)。

?

1234567

var fs = require('fs'); fs.readFile('fhgwgdz.txt', function(err, data) { if (err) { return console.error(err); }; console.log(data.toString('utf8'));});

客户端JavaScript 库的一致性要稍微差些,不过最常见的模式是,针对成败这两种情形各规定一个单独的回调。jQuery 的Ajax

方法就遵循了这个模式。

?

1234

$.get('/data', { success: successHandler, failure: failureHandler});

不管API 形态像什么,始终要记住的是,只能在回调内部处理源于回调的异步错误。

三、未捕获异常的处理

如果是从回调中抛出异常的,则由那个调用了回调的人负责捕获该异常。但如果异常从未被捕获,又会怎么样?这时,不同的JavaScript环境有着不同的游戏规则……

1. 在浏览器环境中

现代浏览器会在开发人员控制台显示那些未捕获的异常,接着返回事件队列。要想修改这种行为,可以给window.onerror

附加一个处理器。如果windows.onerror 处理器返回true,则能阻止浏览器的默认错误处理行为。

?

123

window.onerror = function(err) { return true; //彻底忽略所有错误};

在成品应用中, 会考虑某种JavaScript 错误处理服务, 譬如Errorception。Errorception

提供了一个现成的windows.onerror 处理器,它向应用服务器报告所有未捕获的异常,接着应用服务器发送消息通知我们。

2. 在Node.js 环境中

在Node 环境中,window.onerror 的类似物就是process 对象的uncaughtException 事件。正常情况下,Node

应用会因未捕获的异常而立即退出。但只要至少还有一个uncaughtException 事件处理

器,Node 应用就会直接返回事件队列。

?

123

process.on('uncaughtException', function(err) { console.error(err); //避免了关停的命运!});

但是,自Node 0.8.4 起,uncaughtException 事件就被废弃了。据其文档所言,对异常处理而言,uncaughtException

是一种非常粗暴的机制,请勿使用uncaughtException,而应使用Domain 对象。

Domain 对象又是什么?你可能会这样问。Domain 对象是事件化对象,它将throw 转化为'error'事件。下面是一个例子。

?

123456789

var myDomain = require('domain').create();myDomain.run(function() { setTimeout(function() { throw new Error('Listen to me!') }, 50);});myDomain.on('error', function(err) { console.log('Error ignored!');});

源于延时事件的throw 只是简单地触发了Domain 对象的错误处理器。

Error ignored!

很奇妙,是不是?Domain 对象让throw

语句生动了很多。不管在浏览器端还是服务器端,全局的异常处理器都应被视作最后一根救命稻草。请仅在调试时才使用它。

四、几种解决方案

下面对几种解决方案的讨论主要集中于上面提到的两个核心问题上,当然也会考虑其他方面的因素来评判其优缺点。

1、Async.js

首先是Node中非常著名的Async.js,这个库能够在Node中展露头角,恐怕也得归功于Node统一的错误处理约定。

而在前端,一开始并没有形成这么统一的约定,因此使用Async.js的话可能需要对现有的库进行封装。

Async.js的其实就是给回调函数的几种常见使用模式加了一层包装。比如我们需要三个前后依赖的异步操作,采用纯回调函数写法如下:

?

12345678910111213141516

asyncOpA(a, b, (err, result) => { if (err) { handleErrorA(err); } asyncOpB(c, result, (err, result) => { if (err) { handleErrorB(err); } asyncOpB(d, result, (err, result) => { if (err) { handlerErrorC(err); } finalOp(result); }); });});

如果我们采用async库来做:

?

12345678910111213141516171819202122

async.waterfall([ (cb) => { asyncOpA(a, b, (err, result) => { cb(err, c, result); }); }, (c, lastResult, cb) => { asyncOpB(c, lastResult, (err, result) => { cb(err, d, result); }) }, (d, lastResult, cb) => { asyncOpC(d, lastResult, (err, result) => { cb(err, result); }); }], (err, finalResult) => { if (err) { handlerError(err); } finalOp(finalResult);});

可以看到,回调函数由原来的横向发展转变为纵向发展,同时错误被统一传递到最后的处理函数中。

其原理是,将函数数组中的后一个函数包装后作为前一个函数的末参数cb传入,同时要求:

每一个函数都应当执行其cb参数;cb的第一个参数用来传递错误。我们可以自己写一个async.waterfall的实现:

?

12345678910111213141516171819202122

let async = { waterfall: (methods, finalCb = _emptyFunction) => { if (!_isArray(methods)) { return finalCb(new Error('First argument to waterfall must be an array of functions')); } if (!methods.length) { return finalCb(); } function wrap(n) { if (n === methods.length) { return finalCb; } return function (err, ...args) { if (err) { return finalCb(err); } methods[n](...args, wrap(n + 1)); } } wrap(0)(false); }};

Async.js还有series/parallel/whilst等多种流程控制方法,来实现常见的异步协作。

Async.js的问题:

在外在上依然没有摆脱回调函数,只是将其从横向发展变为纵向,还是需要程序员熟练异步回调风格。

错误处理上仍然没有利用上try-catch和throw,依赖于“回调函数的第一个参数用来传递错误”这样的一个约定。

2、Promise方案

ES6的Promise来源于Promise/A+。使用Promise来进行异步流程控制,有几个需要注意的问题,

把前面提到的功能用Promise来实现,需要先包装异步函数,使之能返回一个Promise:

?

12345678910

function toPromiseStyle(fn) { return (...args) => { return new Promise((resolve, reject) => { fn(...args, (err, result) => { if (err) reject(err); resolve(result); }) }); };}

这个函数可以把符合下述规则的异步函数转换为返回Promise的函数:

回调函数的第一个参数用于传递错误,第二个参数用于传递正常的结果。接着就可以进行操作了:

?

123456789101112131415

let [opA, opB, opC] = [asyncOpA, asyncOpB, asyncOpC].map((fn) => toPromiseStyle(fn)); opA(a, b) .then((res) => { return opB(c, res); }) .then((res) => { return opC(d, res); }) .then((res) => { return finalOp(res); }) .catch((err) => { handleError(err); });

通过Promise,原来明显的异步回调函数风格显得更像同步编程风格,我们只需要使用then方法将结果传递下去即可,同时return也有了相应的意义:

在每一个then的onFullfilled函数(以及onRejected)里的return,都会为下一个then的onFullfilled函数(以及onRejected)的参数设定好值。

如此一来,return、try-catch/throw都可以使用了,但catch是以方法的形式出现,还是不尽如人意。

3、Generator方案

ES6引入的Generator可以理解为可在运行中转移控制权给其他代码,并在需要的时候返回继续执行的函数。利用Generator可以实现协程的功能。

将Generator与Promise结合,可以进一步将异步代码转化为同步风格:

?

1234567891011

function* getResult() { let res, a, b, c, d; try { res = yield opA(a, b); res = yield opB(c, res); res = yield opC(d); return res; } catch (err) { return handleError(err); }}

然而我们还需要一个可以自动运行Generator的函数:

?

123456789101112131415161718192021222324252627282930

function spawn(genF, ...args) { return new Promise((resolve, reject) => { let gen = genF(...args); function next(fn) { try { let r = fn(); if (r.done) { resolve(r.value); } Promise.resolve(r.value) .then((v) => { next(() => { return gen.next(v); }); }).catch((err) => { next(() => { return gen.throw(err); }) }); } catch (err) { reject(err); } } next(() => { return gen.next(undefined); }); });}

用这个函数来调用Generator即可:

?

1234567

spawn(getResult) .then((res) => { finalOp(res); }) .catch((err) => { handleFinalOpError(err); });

可见try-catch和return实际上已经以其原本面貌回到了代码中,在代码形式上也已经看不到异步风格的痕迹。

类似的功能有co/task.js等库实现。

4、ES7的async/await

ES7中将会引入async function和await关键字,利用这个功能,我们可以轻松写出同步风格的代码,

同时依然可以利用原有的异步I/O机制。

采用async function,我们可以将之前的代码写成这样:

?

12345678910111213

async function getResult() { let res, a, b, c, d; try { res = await opA(a, b); res = await opB(c, res); res = await opC(d); return res; } catch (err) { return handleError(err); }} getResult();

和Generator & Promise方案看起来没有太大区别,只是关键字换了换。

实际上async

function就是对Generator方案的一个官方认可,将之作为语言内置功能。

async function的缺点:

await只能在async function内部使用,因此一旦你写了几个async function,或者使用了依赖于async

function的库,那你很可能会需要更多的async function。

目前处于提案阶段的async

function还没有得到任何浏览器或Node.JS/io.js的支持。Babel转码器也需要打开实验选项,并且对于不支持Generator的浏览器来说,还需要引进一层厚厚的regenerator

runtime,想在前端生产环境得到应用还需要时间。

以上就是本文的全部内容,希望对大家的学习有所帮助。

js如何异步执行方法

function myThread(callback){

  return setTimeout(1000*10,function(){

    $("#div").append("<p>hello</p>");//10秒后在div中加一个行,然后在执行callback函数

    callback();

  });

}

 用回调函数

function A(fun){    

 var temp = 100;   

 temp = temp * temp;    

 window.setTimeout(function(){  

       fun(temp);

    },0);

 alert("a函数:"+temp);

}

function B(r){    

 alert("b函数"+r);

}

A(B);// 调用

js/javascript 异步执行方法

var xmlHttp;

function createXMLHttpRequest(){

//Mozilla 浏览器(将XMLHttpRequest对象作为本地浏览器对象来创建)

if(window.XMLHttpRequest){ //Mozilla 浏览器

xmlHttp = new XMLHttpRequest();

}else if(window.ActiveXObject) { //IE浏览器

//IE浏览器(将XMLHttpRequest对象作为ActiveX对象来创建)

try{

xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");

}catch(e){

try {

xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");

}catch(e){}

}

}

if(xmlHttp == null){

alert("不能创建XMLHttpRequest对象");

return false;

}

}

//用于发出异步请求的方法

function sendAsynchronRequest(url,parameter,callback){

createXMLHttpRequest();

if(parameter == null){

//设置一个事件处理器,当XMLHttp状态发生变化,就会出发该事件处理器,由他调用

//callback指定的javascript函数

xmlHttp.onreadystatechange = callback;

//设置对拂去其调用的参数(提交的方式,请求的的url,请求的类型(异步请求))

xmlHttp.open("GET",url,true);//true表示发出一个异步的请求。

xmlHttp.send(null);

}else{

xmlHttp.onreadystatechange = callback;

xmlHttp.open("POST",url,true);

xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;");

xmlHttp.send(parameter);

}

}

//以上代码是通用的方法,接下来是调用以上的方法

function loadPros(title,count,pid,cid,level){

// 调用异步请求方法

url = "。。。。。。。。";

sendAsynchronRequest(url,null,loadCallBack);

}

// 指定回调方法

function loadCallBack(){

try

{

if (xmlHttp.readyState == 4) {

if (xmlHttp.status == 200) {

if(xmlHttp.responseText != null && xmlHttp.responseText != ""){

var divProid = document.getElementById('videolist');

divProid.innerHTML = xmlHttp.responseText;

for(i=0;i<len;i++)

{

var video_url = document.getElementById("videolist"+i+"").href;

if(video_url != undefined && video_url != null && video_url != ""){

window.location.href = video_url;

}

}

}

}

}

if (xmlHttp.readyState == 1)

{

//alert("正在加载连接对象......");

}

if (xmlHttp.readyState == 2)

{

//alert("连接对象加载完毕。");

}

if (xmlHttp.readyState == 3)

{

//alert("数据获取中......");

}

}

catch (e)

{

//alert(e);

}

}

  • 本文相关:
  • 浅谈关于js下大批量异步任务按顺序执行解决方案一点思考
  • js异步加载的三种解决方案
  • js中同步与异步处理的方法和区别总结
  • nodejs异步回调的优雅处理方法
  • javascript 异步加载详解(浏览器在javascript的加载方式)
  • javascript 文件的同步加载与异步加载实现原理
  • js 异步操作回调函数如何控制执行顺序
  • js 清除字符串数组中,重复元素的实现方法
  • ie和firefox浏览器的event事件兼容性汇总
  • js ie和ff兼容性问题汇总
  • 关于javascript 对象(object)的prototype
  • 分享js数组求和与求最大值的方法
  • js实现div内部的文字或图片自动循环滚动代码
  • layui 富文本图片上传接口与普通按钮 文件上传接口的例子
  • bootstrap fileinput 4.4.7文件上传实例详解
  • 详解关于react-redux中的connect用法介绍及原理解析
  • javascript框架设计读书笔记之字符串的扩展和修复
  • 如何优雅地写js异步代码
  • javascript中异步操作的异常怎么处理
  • js如何异步执行方法
  • js/javascript 异步执行方法
  • 异步javascript有哪些
  • javascript脚本如何异步加载,有什么作用
  • 如何实现javascript的方法中等待异步操作完
  • javascript异步加载几种方式总结
  • JavaScript的异步实现机制,是怎么实现的?
  • 如何在javascript中异步调用一个函数
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全基础知识javascript类库表单特效广告代码网页特效黑客性质javascript技巧domnode.jsjs其它首页javascriptjavascript技巧浅谈关于js下大批量异步任务按顺序执行解决方案一点思考js异步加载的三种解决方案js中同步与异步处理的方法和区别总结nodejs异步回调的优雅处理方法javascript 异步加载详解(浏览器在javascript的加载方式)javascript 文件的同步加载与异步加载实现原理js 异步操作回调函数如何控制执行顺序js 清除字符串数组中,重复元素的实现方法ie和firefox浏览器的event事件兼容性汇总js ie和ff兼容性问题汇总关于javascript 对象(object)的prototype分享js数组求和与求最大值的方法js实现div内部的文字或图片自动循环滚动代码layui 富文本图片上传接口与普通按钮 文件上传接口的例子bootstrap fileinput 4.4.7文件上传实例详解详解关于react-redux中的connect用法介绍及原理解析javascript框架设计读书笔记之字符串的扩展和修复js刷新页面方法大全js中settimeout()的用法详解js截取字符串常用方法详细整理js页面跳转常用的几种方式js打开新窗口的2种方式js数组与字符串的相互转换方法js设置cookie、读取cookie、删除js 将json字符串转换为json对象的js删除数组里的某个元素方法javascript深入理解js闭包微信小程序实现图片预览功能将\u8bf7\u9009\u62e9 这样的字符串转为汉javascript 动态添加事件代码浅析javascript中的事件代理javascript阻止scroll事件多次执行的思路replace()方法查找字符使用示例javascript 函数节流详解及方法总结javascript实时显示当天日期的方法给javascript数组插入一条记录的代码可以用来调试javascript错误的解决方案
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved