Promise
创建一个简单的promise对象:
// 创建并执行Promise,传入匿名函数
new Promise( (resolve, reject) => {
let timeOut = Math.random() * 2;
log('set timeout to: ' + timeOut + ' seconds.');
// 1秒后执行判断,小于1输出'成功',否则输出'错误'
setTimeout(function () {
if (timeOut < 1) {
log('call resolve()...');
resolve('200 OK');
}
else {
log('call reject()...');
reject('timeout in ' + timeOut + ' seconds.');
}
}, timeOut * 1000);
}).then(function(resolve){
console.log('成功:' + resolve)
}).catch(function(reject){
console.log('失败:' + reject)
});
// then对应调用resolve回调函数;catch对应调用reject回调函数
// resolve('200 OK')把"200 OK"作为参数传递
串联多个promise:
const promise1 = new Promise(fnAsync(){...});
const promise2 = new Promise(fnAsync(){...});
const promise3 = new Promise(fnAsync(){...});
// promise1成功执行后再执行promise2,再是promise3
promise1.then(promise2).then(promise3);
并联多个promise:
const promise1 = new Promise(fnAsync(){...});
const promise2 = new Promise(fnAsync(){...});
const promise3 = new Promise(fnAsync(){...});
// promise1/2/3均成功后再执行then(一个失败也不会执行then)
Promise.all([promise1, promise2, promise3]).then(callback(){...});
// promise1/2/3任意一个成功后执行then
Promise.race([promise1, promise2, promise3]).then(callback(){...})
携带特定参数,包裹promise:
const fs = require('fs')
function readFileAsync(path){
return new Promise((resolve, reject) => {
fs.readFile(path, (err, data) => {
if(err) reject(err)
else resolve(data)
})
})
}
// 执行函数
readFileAsync('./test.json')
.then(data => {
data = data.JSON.parse(data);
console.log(data);
})
.catch(err => {
console.log(err);
})
使用util模块:
const util = require('util')
// 注意传参模式
util.promisify(fs.readFile)('./test.json')
.then(JSON.parse)
.then(data => {
console.log(data.name);
})
.catch(err => {
console.log(err);
})
async/await
"async" 定义的函数本质是Promise对象(即可以通过 ".catch()" 捕获错误):
async function timeout() {
return 'hello world'
}
console.log(timeout());
console.log('先执行!');
/* 打印结果:
先执行!
Promise { 'hello world' }
*/
"await" 表示停在该函数上等待,其结束后再执行之后代码:
// 2s 之后返回双倍的值
function doubleAfter2seconds(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2 * num)
}, 2000);
} )
}
// 定义async函数
async function testResult() {
console.log('---2s后打印resolve---');
let result = await doubleAfter2seconds(30);
setTimeout(() => {
console.log('再过1.5s后打印"await"后语句')
}, 1500)
console.log(`result:${result}`);
}
testResult(30);
/* 打印结果:
---2s后打印resolve---
result:60
再过1.5s后打印"await"后语句
*/
"await" 与 ".then()" 类似,前者优势是传参方便。
检验知识
前端一道面试题:
async function async1() {
console.log( 'async1 start' );
await async2();
console.log( 'async1 end' );
}
async function async2() {
console.log( 'async2' );
}
console.log( 'script start' );
setTimeout( function () {
console.log( 'setTimeout' );
}, 0);
async1();
new Promise(function (resolve) {
console.log( 'promise1' );
resolve();
}).then(function () {
console.log( 'promise2' );
});
console.log( 'script end' );
答案:
script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout
理解:
1. js是单线程
2. 分成3个部分:主线程、异步栈、计时器
3. 异步函数内的同步代码(如console.log)会立即执行
4. "await" 和 ".then()" 会阻塞异步对象本身,线程回到主线程
5. "await"后的代码 和 ".then()"内的代码 会被推入"异步栈"中
6. "异步栈"内的代码是"先进后出"
7. 计时器会先"挂起",到达指定时间后"请求"执行,但会被"阻塞",所以总是比设定时间执行稍晚计时器代码