关于Promise 对象,阮一峰大神在Es6入门中写过,这里就不再累赘了!大家可以在本文底部,点击查看Promise 文档。其实Promise 最早是源于社区,jquery的deferred对象,也有类似Promise的实现。我之前在判断文章中所有图片是否加载完成一文中有所提及!今天主要讲讲Promise及Async/Await的一些应用。
简单的停顿执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var sleep = function (time) { return new Promise(function (resolve, reject) { setTimeout(function () { resolve(); }, time); }) };
var start = async function () { console.log('start'); await sleep(3000); console.log('end'); };
start();
|
上面代码中,控制台先输出start,稍等3秒后,输出了end。
获得返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var sleep = function (time) { return new Promise(function (resolve, reject) { setTimeout(function () { // 返回 ‘ok’ resolve('ok'); }, time); }) };
var start = async function () { let result = await sleep(3000); console.log(result); // 收到 ‘ok’ }; start()
|
await等待的虽然是promise对象,但不必写.then(..),直接可以得到返回值。
捕捉错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| var sleep = function (time) { return new Promise(function (resolve, reject) { setTimeout(function () { // 模拟出错了,返回 ‘error’ reject('error'); }, time); }) };
var start = async function () { try { console.log('start'); await sleep(3000); // 这里得到了一个返回错误
// 所以以下代码不会被执行了 console.log('end'); } catch (err) { console.log(err); // 这里捕捉到错误 `error` } }; start()
|
既然.then(..)不用写了,那么.catch(..)也不用写,可以直接用标准的try catch语法捕捉错误。
循环多个await
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var sleep = function (time) { return new Promise(function (resolve, reject) { setTimeout(function () { resolve(); }, time); }) }; var start = async function () { for (var i = 1; i <= 10; i++) { console.log(`当前是第${i}次等待..`); await sleep(1000); } }; start()
|
会输出:
1 2 3 4 5 6 7 8 9 10 11
| 当前是第1次等待.. Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined} 当前是第2次等待.. 当前是第3次等待.. 当前是第4次等待.. 当前是第5次等待.. 当前是第6次等待.. 当前是第7次等待.. 当前是第8次等待.. 当前是第9次等待.. 当前是第10次等待..
|
每隔1s输出一次。
经典面试题目
我之前提到的setTimeout和for循环结合,假如有如下代码:
1 2 3 4 5 6 7 8 9
| for (var i = 0; i < 5; i++) { (function(j) { // j = i setTimeout(function() { console.log(new Date, j); }, 1000); })(i); }
console.log(new Date, i);
|
如何对其进行改进,让每隔1s输出一个数字,顺序是:0 -> 1 -> 2 -> 3 -> 4 -> 5
不用es6如下写
1 2 3 4 5 6 7 8 9 10 11
| for (var i = 0; i < 5; i++) { (function(j) { setTimeout(function() { console.log(new Date, j); }, 1000 * j); // 这里修改 0~4 的定时器时间 })(i); }
setTimeout(function() { // 这里增加定时器,超时设置为 5 秒 console.log(new Date, i); }, 1000 * i);
|
用Es6的Promise的写法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const tasks = []; // 这里存放异步操作的 Promise const output = (i) => new Promise((resolve) => { setTimeout(() => { console.log(new Date, i); resolve(); }, 1000 * i); });
// 生成全部的异步操作 for (var i = 0; i < 5; i++) { tasks.push(output(i)); }
// 异步操作完成之后,输出最后的 i Promise.all(tasks).then(() => { setTimeout(() => { console.log(new Date, i); }, 1000); });
|
用ES7 async和await的写法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| const sleep = (timeountMS) => new Promise((resolve) => { setTimeout(resolve, timeountMS); });
(async () => { // 声明即执行的 async 函数表达式 for (var i = 0; i < 5; i++) { await sleep(1000); console.log(new Date, i); }
await sleep(1000); console.log(new Date, i); })();
|
上面是对es6的Promise及es7的Async/Await的简单应用,关于ES6的Promise,可以查看阮一峰大神的文档:[http://es6.ruanyifeng.com/#docs/promise
Yours sincerely AppleSun