JavaScript中的两种异步处理方式:1、利用“Promise”来处理异步,它可以帮忙管理异步方式返回的代码;2、利用“async/await”来处理异步,可以将异步事件用同步语法来处理。
本教程操作环境:windows7系统、javascript1.8.5版、Dell G3电脑。
Promise
(1)promise对象是commonJS工作组提出的一种规范,一种模式,目的是为了异步编程提供统一接口。
(2)promise是一种模式,promise可以帮忙管理异步方式返回的代码。他讲代码进行封装并添加一个类似于事件处理的管理层。我们可以使用promise来注册代码,这些代码会在在promise成功或者失败后运行。
(3)promise完成之后,对应的代码也会执行。我们可以注册任意数量的函数再成功或者失败后运行,也可以在任何时候注册事件处理程序。
(4)promise有两种状态:1、等待(pending);2、完成(settled)。
promise会一直处于等待状态,直到它所包装的异步调用返回/超时/结束。
(5)这时候promise状态变成完成。完成状态分成两类:1、解决(resolved);2、拒绝(rejected)。
(6)promise解决(resolved):意味着顺利结束。promise拒绝(rejected)意味着没有顺利结束。
//promise var p=new Promise(function(resolved)) //在这里进行处理。也许可以使用ajax setTimeout(function(){ var result=10*5; if(result===50){ resolve(50); }else{ reject(new Error('Bad Math')); } },1000); }); p.then(function(result){ console.log('Resolve with a values of %d',result); }); p.catch(function(){ console.error('Something went wrong'); });
(1)代码的 关键在于setTimeout()的调用。
(2)重要的是,他调用了函数resolve()和reject()。resolve()函数告诉promise用户promise已解决;reject()函数告诉promise用户promise未能顺利完成。
(3)另外还有一些使用了promise代码。注意then和catch用法,可以将他们想象成onsucess和onfailure事件的处理程序。
(4)巧妙地方是,我们将promise处理与状态分离。也就是说,我们可以调用p.then(或者p.catch)多少次都可以,不管promise是什么状态。
(5)promise是ECMAscript 6管理异步代码的标准方式,javascript库使用promise管理ajax,动画,和其他典型的异步交互。
简单的说,它的思想是:每一个异步任务返回一个promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:
f1.then(f2);
f1要进行如下改写(使用jquery的实现):
function f1(){ var dfd=$.deferred(); settimeout(function(){ //f1的任务代码 dfd.resolve(); },500); return dfd.promise; }
这样写的优点:回调函数写成了链式写法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以实现很多强大的功能。
比如,指定多个回调函数
f1().then(f2).then(f3);
再比如,指定发生的错误时的回调函数:
f1().then(f2).fail(f3);
而且,它有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。
所以你不用担心错过某一个事件或者信号。
这种方法的缺点:编写和理解都相对比较难。
async await
从 ES6 Promise 问世之后,异步代码从回调地狱逐渐变成了优雅的函数式管道处理,但对于不熟悉度的开发者来说,只不过是从回调地狱变成了 Promise 地狱而已。
在 ES8 中规范了新的 async
/await
,虽然只是 Promise 和 Generator Function组合在一起的语法糖,但通过 async
/await
便可以将异步事件用同步语法来处理,就好像是老树开新花一样,写起来的风格与 Promise 完全不同:
function wait(time, fn) { return new Promise(resolve => { setTimeout(() => { console.log('wait:', time) resolve(fn ? fn() : time) }, time) }) } await wait(500, () => console.log('bar')) console.log('foo') // wait: 500 // bar // foo
通过把 setTimeout
包装成 Promise,再用 await
关键字调用,可以看到结果会是同步执行的先出现 bar
,再出现 foo
,也就是开头提到的将异步事件写成同步处理。
再看一个例子:
async function withAsyncAwait() { for(let i = 0; i < 5; i++) { await wait(i*500, () => console.log(i)) } }await withAsyncAwait() // wait: 0 // 0 // wait: 500 // 1 // wait: 1000 // 2 // wait: 1500 // 3 // wait: 2000 // 4
代码中实现了withAsyncAwait
函数,用 for
循环及 await
关键字反复执行 wait
函数;此处执行时,循环每次会按顺序等待不同的秒数再执行下一次循环。
在使用 async
/await
时,由于 await
关键字只能在 async function 中执行,使用时务必要记得要同时使用。
另外在用循环处理异步事件时,需要注意在 ES6 之后提供的很多 Array 方法都不支持 async
/await
语法,如果这里用 forEach
取代 for
,结果会变成同步执行,每隔 0.5 秒就打印出数字:
【相关推荐:javascript学习教程】
以上是JavaScript有哪两种异步处理方式的详细内容。更多信息请关注PHP中文网其他相关文章!