爬虫基于回调和事件的方式去实现,回调也是被诟病已久的问题尤其是callback这种,无论是阅读还是调试都很费劲,甚至我们连代码的堆栈都看不到,这是一种反人类的写法,Promise来拜托这种痛苦的方式
传统方式实现动画效果:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Promise animation</title>
<style>
.ball{
width:40px;
height:40px;
border-radius: 20px;/**圆角**/
}
.ball1{
background: red;
}
.ball2{
background: yellow;
}
.ball3{
background: green;
}
</style>
<script src="./node_modules/bluebird/js/browser/bluebird.js"></script>
</head>
<body onload="init();">
<div class="ball ball1" ></div>
<div class="ball ball2" ></div>
<div class="ball ball3" ></div>
<script type="text/javascript">
function init(){
//首先拿到这三个小球
var ball1 = document.querySelector('.ball1')
var ball2 = document.querySelector('.ball2')
var ball3 = document.querySelector('.ball3')
/**
* 动画函数
* @param {Object} ball 球
* @param {Object} distance 位置,把球移动到哪里
* @param {Object} cb 回调的callback
*/
function animate(ball,distance,cb){
alert(ball)
//设定一个延时
setTimeout(function(){
//拿到球现在距离左边距的位置
var marginLeft = parseInt(ball.style.marginLeft,10)
//判断左边距移动到和我们传入的distance的时候
//重叠,说明动画执行完毕
if(marginLeft===distance){
//直接调用回调函数
cb && cb()
}else{//小球没有达到我们预期的位置
//球在我们期望位置的左侧
if(marginLeft<distance){
marginLeft++
}else{//在右侧
marginLeft--
}
//调整球的样式
ball.style.marginLeft = marginLeft + 'px'
//不断重复去做,直到移动到我们所期望的位置
animate(ball,distance,cb)
}
},13)
//时间越短,动画越流畅,1秒钟60帧
}
//调用动画_传统方式来执行动画
animate(ball1,100,function(){//球从左侧向右侧移动100像素
animate(ball2,200,function(){
animate(ball3,300,function(){
//移动完毕之后继续移动ball3
animate(ball3,150,function(){
animate(ball2,150,function(){
animate(ball1,150,function(){
//end
})
})
})
})
})
})
}
</script>
</body>
</html>
运行结果如下:
Promise方式如下:
再使用Promise方法之前先导入npm install bluebird模块,之后再用script标签来引用
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Promise animation</title>
<style>
.ball{
width:40px;
height:40px;
border-radius: 20px;/**圆角**/
}
.ball1{
background: red;
}
.ball2{
background: yellow;
}
.ball3{
background: green;
}
</style>
<script src="./node_modules/bluebird/js/browser/bluebird.js"></script>
</head>
<body>
<div class="ball ball1" ></div>
<div class="ball ball2" ></div>
<div class="ball ball3" ></div>
<script type="text/javascript">
//首先拿到这三个小球
var ball1 = document.querySelector('.ball1')
var ball2 = document.querySelector('.ball2')
var ball3 = document.querySelector('.ball3')
/**
* 动画函数
* @param {Object} ball 球
* @param {Object} distance 位置,把球移动到哪里
* @param {Object} cb 回调的callback
*/
function animate(ball,distance,cb){
//设定一个延时
setTimeout(function(){
//拿到球现在距离左边距的位置
var marginLeft = parseInt(ball.style.marginLeft,10)
//判断左边距移动到和我们传入的distance的时候
//重叠,说明动画执行完毕
if(marginLeft===distance){
//直接调用回调函数
cb && cb()
}else{//小球没有达到我们预期的位置
//球在我们期望位置的左侧
if(marginLeft<distance){
marginLeft++
}else{//在右侧
marginLeft--
}
//调整球的样式
ball.style.marginLeft = marginLeft + 'px'
//不断重复去做,直到移动到我们所期望的位置
animate(ball,distance,cb)
}
},13)
//时间越短,动画越流畅,1秒钟60帧
}
//如何用promise来执行动画呢,先安装一个库npm install bluebird
//要安装在该页面同层的下面
function promiseAnimate(ball,distance){
return new Promise(function(resolve,reject){
function _animate(){
//设定一个延时
setTimeout(function(){
//拿到球现在距离左边距的位置
var marginLeft = parseInt(ball.style.marginLeft,10)
if(marginLeft===distance){
//直接调用回调函数
resolve()
}else{//小球没有达到我们预期的位置
//球在我们期望位置的左侧
if(marginLeft<distance){
marginLeft++
}else{//在右侧
marginLeft--
}
//调整球的样式
ball.style.marginLeft = marginLeft + 'px'
//不断重复去做,直到移动到我们所期望的位置
_animate()
}
},13)
//时间越短,动画越流畅,1秒钟60帧
}
//启动调用
_animate()
})
}
promiseAnimate(ball1,100)
.then(function(){
return promiseAnimate(ball2,200)
})
.then(function(){
return promiseAnimate(ball3,300)
})
.then(function(){
return promiseAnimate(ball3,150)
})
.then(function(){
return promiseAnimate(ball2,150)
})
.then(function(){
return promiseAnimate(ball1,150)
})
</script>
</body>
</html>
运行效果同上。
在callback中,如果调换动画的执行顺序或者增加几个或者减少几个,需要重新更改代码;
如果用promise则是一个线性的控制无论是阅读还是维护的体验上都得到了提升,
这仅仅是在浏览器中的应用,在NodeJs中回调的场景更多也更残忍,
尤其是有远程API同步和数据库查询、文件读写操作的时候,Promise就能解决这些痛点
并且也远不止于此
了解Promise需要了解如下知识
1.ES6的Promise语言标准、Promise/A+规范
Promise是针对JavaScript中的异步场景中的解决方案(传统:回调、事件机制、订阅者、等)
Promise是一个对象和JavaScript中普通的对象没有什么区别,
同时它也是一种规范,异步操作约定了统一的接口,表示一个异步操作的最终结果,
以同步的方式来写代码,执行的操作是异步的,又保证了程序的执行顺序是同步的,
只有三种状态:未完成、已完成、失败
其中中间转换过程只能发生一次并且是不可逆的;
意思是指:要么从未完成到已完成,要么从未完成到失败。
那Promise/A+规范是什么呢?
升级版,行为标准 扩展了原来的规范,约定俗成的行为,总之是一个更为标准的
不同之处:
A+规范通过术语thenable来区分promise对象
A+定义onFulfiled/onRejected必须是作为函数来调用,而且调用过程必须是异步的
A+严格定义了then方法链式调用时onFulfilled/onRejected的调用顺序
then方法定义如下:
promiseObj.then(onFulfilled,onRejected)
onFulfilled = function(value){
return promiseObj2
}
onRejected = function(err){}
2.如何使用
链式调用,例如:
promiseAnimate(ball1,100)
.then(function(){
return promiseAnimate(ball2,200)
})
.then(function(){
return promiseAnimate(ball3,300)
})
.then(function(){
return promiseAnimate(ball3,150)
})
.then(function(){
return promiseAnimate(ball2,150)
})
.then(function(){
return promiseAnimate(ball1,150)
})
3.在什么场景下使用
只要是异步编程的地方都可以使用,业务场景简单不要为了使用Promise而使用Promise
Promise库有很多,例如:
bluebird
Q
then.js
es6-promise
ypromise
async
native-promise-only
等等
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。