JavaScript 中稱爲 Promise 對象。Promise 有各種開源實現,在 ES6 中被統一規範,由瀏覽器直接支持。
瀏覽器中的 Promise 對象
在下面的代碼中通過使用 callback 和 Promise 來體驗
- callback 臭名昭著的邪惡金字塔
- Promise 優美的鏈式寫法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>體驗 Promise 的鏈式寫法</title>
<style>
.ball {
width: 40px;
height: 40px;
border-radius: 20px;
}
.ball1, .ball4 {
background: red;
}
.ball2, .ball5 {
background: green;
}
.ball3, .ball6 {
background: yellow;
}
</style>
</head>
<body>
<h1>採用回調函數的方式來實現</h1>
<div class="ball ball1" style="margin-left: 0px;"></div>
<div class="ball ball2" style="margin-left: 0px;"></div>
<div class="ball ball3" style="margin-left: 0px;"></div>
<hr>
<h1>採用 Promise 的方式來實現</h1>
<div class="ball ball4" style="margin-left: 0px;"></div>
<div class="ball ball5" style="margin-left: 0px;"></div>
<div class="ball ball6" style="margin-left: 0px;"></div>
<script>
var ball1 = document.querySelector('.ball1');
var ball2 = document.querySelector('.ball2');
var ball3 = document.querySelector('.ball3');
var ball4 = document.querySelector('.ball4');
var ball5 = document.querySelector('.ball5');
var ball6 = document.querySelector('.ball6');
// /**
// * 方法一:採用 setTimeout 實現
// * @param ball
// * @param distance
// * @param callback
// */
// function animate(ball, distance, callback) {
// setTimeout(function () {
// var marginLeft = parseInt(ball.style.marginLeft);
// if (marginLeft == distance) {
// callback && callback();
// return; // 注意在這裏一定要返回定時器對象,確保後面拿到的是一個新的定時器對象
// } else {
// if (marginLeft < distance) {
// marginLeft++;
// } else {
// marginLeft--;
// }
// }
// ball.style.marginLeft = marginLeft + 'px';
// animate(ball, distance, callback);
// }, 10);
// }
/**
* 方法二:採用 setInterval 實現
* @param ball
* @param distance
* @param callback
*/
function animate(ball, distance, callback) {
var interval = setInterval(function () {
var marginLeft = parseInt(ball.style.marginLeft);
if (marginLeft == distance) {
callback && callback();
clearInterval(interval);
} else {
if (marginLeft < distance) {
marginLeft++;
} else {
marginLeft--;
}
}
ball.style.marginLeft = marginLeft + 'px';
}, 10);
}
animate(ball1, 100, function () {
animate(ball2, 200, function () {
animate(ball3, 300, function () {
animate(ball3, 150, function () {
animate(ball2, 150, function () {
animate(ball1, 150, function () {
//
});
});
});
});
});
});
// /**
// * 採用 Promise 實現
// * @param ball
// * @param distance
// * @returns {Promise}
// */
// function promiseAnimate(ball, distance) {
// return new Promise(function (resolve, reject) {
// var interval = setInterval(function () {
// var marginLeft = parseInt(ball.style.marginLeft);
// if (marginLeft == distance) {
// resolve();
// clearInterval(interval);
// } else {
// if (marginLeft < distance) {
// marginLeft++;
// } else {
// marginLeft--;
// }
// }
// ball.style.marginLeft = marginLeft + 'px';
// }, 10);
// });
// }
//
// promiseAnimate(ball4, 100)
// .then(function () {
// return promiseAnimate(ball5, 200);
// })
// .then(function () {
// return promiseAnimate(ball6, 300);
// })
// .then(function () {
// return promiseAnimate(ball6, 150);
// })
// .then(function () {
// return promiseAnimate(ball5, 150);
// })
// .then(function () {
// return promiseAnimate(ball4, 150);
// });
/**
* 採用 Promise 實現
* @param ball
* @param distance
* @returns {Function}
*/
function promiseAnimate(ball, distance) {
return function () {
return new Promise(function (resolve, reject) {
var interval = setInterval(function () {
var marginLeft = parseInt(ball.style.marginLeft);
if (marginLeft == distance) {
resolve();
clearInterval(interval);
} else {
if (marginLeft < distance) {
marginLeft++;
} else {
marginLeft--;
}
}
ball.style.marginLeft = marginLeft + 'px';
}, 10);
});
}
}
promiseAnimate(ball4, 100)()
.then(promiseAnimate(ball5, 200))
.then(promiseAnimate(ball6, 300))
.then(promiseAnimate(ball6, 150))
.then(promiseAnimate(ball5, 150))
.then(promiseAnimate(ball4, 150))
</script>
</body>
</html>