从Callback到Async的发展过程—实例演示
2018-03-14 16:08
267 查看
引言:
前端开发中,异步处理必不可少;过去,我们经常用回调函数来完成异步处理,因此也经常产生回调地狱(
callback hell);
今天,我们用实例来对比异步处理的方法;
是时候用
async来处理我们的异步流程了。Step 1: 回调函数
Callback回调函数: 是将一个函数作为参数,传递给另一个函数,然后在外部函数中调用该函数来完成某种例程或动作。用法:在函数内部调用函数
2. 用callback
实现小球移动的方法;
function move(ele, target, callback) { let left = parseInt(getComputedStyle(ele)["left"]); let timer = setInterval(function () { if (left >= target) { clearInterval(timer); callback(); } else { left += 2; ele.style.left = left + "px"; } }, 4) }
2. 执行运动;
move(ball1, 200, function () { move(ball2, 400, function () { move(ball3, 600, function () { alert("callback"); }); }) })
Step 2: Promise对象Promise
Promise: 是一个返回值的代理,它允许您将处理程序与异步操作的最终成功值或失败原因相关联。 这使异步方法可以像同步方法那样返回值:不是立即返回最终值,而是异步方法返回一个
Promise,以便在未来的某个时间点提供该值。用法:
Promise对象是由关键字
new及其构造函数来创建的。该函数接收一个函数(
executor function)作为它的参数。这个函数接受两个函数——
resolve和
reject——作为其参数。当异步任务顺利完成且返回结果值时,会调用
resolve函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用
reject函数。
1. 用Promise
实现小球移动的方法;
// 让move方法拥有Promise功能 function move(ele, target) { return new Promise(function (resolve, reject) { let left = parseInt(getComputedStyle(ele)["left"]); let timer = setInterval(function () { if (left >= target) { clearInterval(timer); resolve(); } else { left += 2; ele.style.left = left + "px"; } }, 4) }) }
2. 执行运动,调用Promise.then()
方法;
move(ball1, 200).then(function () { return move(ball2, 400); }).then(function () { return move(ball3, 600); }).then(function () { alert("promise"); })
Step 3: Generator对象 Generator
Generator:生成器函数在函数执行时能暂停,还能从暂停处继续执行,相当于将函数分段执行。用法:必须用
.next()配合
yield关键字使用;例如:
function *gen(){ yield 10; y=yield 'foo'; yield y; } var gen_obj=gen(); console.log(gen_obj.next()); // 执行 yield 10,返回 10 console.log(gen_obj.next()); // 执行 yield 'foo',返回 'foo' console.log(gen_obj.next(10)); // 将 10 赋给上一条 yield 'foo' 的左值,即执行 y=10,返回 10 console.log(gen_obj.next()); // 执行完毕,value 为 undefined,done 为 true
1. 用Genertor
实现小球移动的方法;
// 函数move方法调用上面Promise中的move方法; function move(ele, target) { return new Promise(function (resolve, reject) { let left = parseInt(getComputedStyle(ele)["left"]); let timer = setInterval(function () { if (left >= target) { clearInterval(timer); resolve(); } else { left += 2; ele.style.left = left + "px"; } }, 4) }) }
2. 执行运动,需要分布执行,但此方法需要手动分行执行;
let g = m(); g.next(); //让第一个小球运动; g.next(); //让第二个小球运动; g.next(); //让第三个小球运动;
3. 使用co
库迭代generator
执行器;
function co(it) { return new Promise(function (resolve, reject) { function next(d) { let { value, done } = it.next(d); if (!done) { value.then(function (data) { next(data) }, reject) } else { resolve(value); } }; next(); }); } // 一行代码实现函数执行,但是需要引入co库; co(m()).then(function () { alert("generator"); })
Step 4: async/await函数 async/await
async: 异步函数声明定义了一个异步函数,它返回一个
AsyncFunction对象。当
async函数执行,返回一个
Promise对象;用法:用
async声明函数,函数内配合
await使用。
1. 用 async/await
实现小球移动的方法;
// 调用上面的move()方法; function move(ele, target) { return new Promise(function (resolve, reject) { let left = parseInt(getComputedStyle(ele)["left"]); let timer = setInterval(function () { if (left >= target) { clearInterval(timer); resolve(); } else { left += 2; ele.style.left = left + "px"; } }, 4) }) }
2. 执行运动,函数内await
方法;
async function a() { await move(ball1, 200); await move(ball2, 400); await move(ball3, 600); } a().then(function () { alert("async") })
结语:
通过上述4种方法的对比,我们可以看出JavaScript这门语言的发展和进步;
ES6+增加了很多实用功能和方法,将有助于前期代码的编写以及后期代码的维护,是时候用
async/await来处理我们的异步操作了。案例源码:
<!DOCTYPE html>文章来源:学什么技术好网
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.container .ball {
width: 100px;
height: 100px;
border-radius: 50%;
position: absolute;
}
.container .ball:nth-child(1) {
background-color: blue;
left: 0;
top: 20px;
}
.container .ball:nth-child(2) {
background-color: yellow;
left: 200px;
top: 150px;
}
.container .ball:nth-child(3) {
background-color: green;
left: 400px;
top: 280px;
}
</style>
</head>
<body>
<div class="container">
<div class="ball"></div>
<div class="ball"></div>
<div class="ball"></div>
</div>
<!-- <script src="Promise.js"></script> -->
<script>
let ball = document.querySelectorAll(".ball");
let [ball1, ball2, ball3] = [...ball];
// 1.回调函数处理;
function move(ele, target, callback) {
let left = parseInt(getComputedStyle(ele)["left"]);
let timer = setInterval(function () {
if (left >= target) {
clearInterval(timer);
callback();
} else {
left += 2;
ele.style.left = left + "px";
}
}, 4)
}
move(ball1, 200, function () { move(ball2, 400, function () { move(ball3, 600, function () { alert("callback"); }); }) })
// 2.promise
// generator、async都是基于promise的发展;
// function move(ele, target) {
// return new Promise(function (resolve, reject) {
// let left = parseInt(getComputedStyle(ele)["left"]);
// let timer = setInterval(function () {
// if (left >= target) {
// clearInterval(timer);
// resolve();
// } else {
// left += 2;
// ele.style.left = left + "px";
// }
// }, 4)
// })
// }
// move(ball1, 200).then(function () {
// return move(ball2, 400);
// }).then(function () {
// return move(ball3, 600);
// }).then(function () {
相关文章推荐
- 多级树集合分裂(SPIHT)算法的过程详解与Matlab实现(8)实例演示
- 实例演示oracle注入获取cmdshell的全过程
- PHP和MySQL存储过程的实例演示
- 存储过程及其实例演示
- 存储过程及其实例演示
- 小学数学课件制作实例:演示半球形成过程
- Oracle 数据库实例启动关闭过程实战演示
- TDD与VTDD系列(四):简单实例演示TDD过程
- 实例演示C++多态的实现过程
- TDD与VTDD系列(四):简单实例演示TDD过程
- SQLServer访问类(带连接池和存储过程演示实例)
- 设备模型5之总线、设备、驱动(实例,简单演示probe过程)
- 在线动画演示各种排序算法过程
- 在Mysql存储过程中使用事务实例
- oracle 存储过程使用实例(含事物和异常处理)
- 存储过程包实例分享
- silverlight+WCF的net.tcp双工通信实例过程
- 存储过程语法及实例
- sql存储过程实例
- 一个字符串分割处理的过程演示