promise
- Promise是一种用于处理异步操作的对象,它可以将异步操作的结果以回调函数的形式返回给调用者。
- Promise对象有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
- 当异步操作执行完毕后,Promise对象的状态会从pending变为fulfilled或rejected,然后调用对应的回调函数。
- Promise 的状态可以通过调用resolve方法将其从pending变为fulfilled,或者通过调用reject方法将其从pending变为rejected。
下面是一个使用Promise对象的例子:
// 创建一个Promise对象
const myPromise = new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
const randomNumber = Math.random();
if (randomNumber > 0.5) {
// 如果生成的随机数大于0.5,则调用resolve方法
resolve(randomNumber);
} else {
// 如果生成的随机数小于等于0.5,则调用reject方法
reject('生成的随机数小于等于0.5');
}
}, 1000);
});
// 调用Promise对象的then方法和catch方法
myPromise
.then((result) => {
console.log('成功:', result);
})
.catch((error) => {
console.log('失败:', error);
});
```
### Promise 的链式回调
```javascript
// 创建一个Promise对象
const myPromise = new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
const randomNumber = Math.random();
if (randomNumber > 0.5) {
// 如果生成的随机数大于0.5,则调用resolve方法
resolve(randomNumber);
} else {
// 如果生成的随机数小于等于0.5,则调用reject方法
reject('生成的随机数小于等于0.5');
}
}, 1000);
});
// 调用Promise对象的then方法和catch方法
myPromise
.then((result) => {
console.log('成功:', result);
return result * 2; // 返回一个新的Promise对象
})
.then((result) => {
console.log('成功:', result);
return result * 2; // 返回一个新的Promise对象
})
.then((result) => {
console.log('成功:', result);
})
.catch((error) => {
console.log('失败:', error);
});
// 在每个then方法中返回一个新的Promise对象,可以实现Promise的链式回调。
使用Promise.all方法实现多异步请求IO
```javascript
const promise1 = new Promise((resolve, reject) => {
// 异步操作1
setTimeout(() => {
resolve('异步操作1的结果');
}, 1000);
});
<pre><code>const promise2 = new Promise((resolve, reject) => {
// 异步操作2
setTimeout(() => {
resolve('异步操作2的结果');
}, 2000);
});
const promise3 = new Promise((resolve, reject) => {
// 异步操作3
setTimeout(() => {
resolve('异步操作3的结果');
}, 3000);
});
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log('所有异步操作都已完成,结果为:', results);
})
.catch((error) => {
console.log('其中一个异步操作失败,错误为:', error);
});
```
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('异步操作1的结果');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('异步操作2的结果');
}, 2000);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('异步操作3的结果');
}, 3000);
});
Promise.race([promise1, promise2, promise3])
.then((result) => {
console.log('最先完成的异步操作结果为:', result);
})
.catch((error) => {
console.log('其中一个异步操作失败,错误为:', error);
});
Generator
- Generator 函数是ES6引入的一种新的函数类型,可以通过yield关键字实现函数的暂停和恢复,从而实现异步编程。
- Generator 函数的执行结果是一个迭代器对象,可以通过next方法控制函数的执行流程。
// 定义一个Generator函数
function* myGenerator() {
console.log('开始执行Generator函数');
const result1 = yield '第一次暂停';
console.log('第一次暂停的结果为:', result1);
const result2 = yield '第二次暂停';
console.log('第二次暂停的结果为:', result2);
console.log('Generator函数执行结束');
}
// 创建一个迭代器对象
const myIterator = myGenerator();
// 第一次调用next方法,开始执行Generator函数
const result1 = myIterator.next();
console.log(result1.value); // 输出:第一次暂停
// 第二次调用next方法,将上一次yield语句的结果传入Generator函数
const result2 = myIterator.next('第一次暂停的结果');
console.log(result2.value); // 输出:第二次暂停
// 第三次调用next方法,将上一次yield语句的结果传入Generator函数
const result3 = myIterator.next('第二次暂停的结果');
console.log(result3.done); // 输出:true
yield
- 本身不会返回任何值,返回值一直为
undefined
- 当下一个
g.next(return 123)
方法中有入参时,此入参会以当前的let result1 = yield first()
的返回值形式返回给g函数,如下:
function* g(){
let r = yield first();
console.log('first-r:', r)
r = yield second();
console.log('second-r:', r)
r = yield trd();
}
const G = g()
G.next() //调用first()
G.next('return 123') //调用second() log: 输出 first-r:return 123
G.next() //调用trd() log: 输出 second-r:undefined
Generator函数的自动执行异步
- 将
g
函数的每个next()
的返回{value, done}
的value
转换为一个Promise
- 然后监听
value.then(onFullFilled, onRejected)
- 分别在
onFullFilled 和 onRejected
中判断并调用g.next()
实现循环自动执行 - 并将上个
next.value
的返回值通过g.next(resultofbefore)
返回给g
函数
// Generator函数的异步自动执行可以通过co库实现,co库可以自动执行Generator函数并将yield语句的结果传入下一个yield语句中,直到函数执行结束。
// 以下是使用co库实现异步自动执行的示例代码:
const co = require('co');
function* myGenerator() {
console.log('开始执行Generator函数');
const result1 = yield Promise.resolve('第一次暂停');
console.log('第一次暂停的结果为:', result1);
const result2 = yield Promise.resolve('第二次暂停');
console.log('第二次暂停的结果为:', result2);
console.log('Generator函数执行结束');
}
co(myGenerator);
async/await
- async/await是ES7引入的一种新的异步编程方式,它是基于Promise实现的语法糖,可以让异步代码看起来更像同步代码,更易于理解和维护。
- async函数返回一个Promise对象,可以使用then方法添加回调函数,也可以使用await关键字等待Promise对象的状态变更。
- async函数内部可以使用await关键字等待一个Promise对象的状态变更,await关键字后面的代码会被暂停执行,直到Promise对象的状态变为resolved或rejected。
- async/await的优点是代码简洁易懂,缺点是无法像Promise那样处理多个并发的异步操作。
async function myAsyncFunction() {
console.log('开始执行async函数');
try { //放在 try/catch中避免promise的reject报错
const result1 = await Promise.resolve('第一次暂停');
console.log('第一次暂停的结果为:', result1);
const result2 = await Promise.resolve('第二次暂停');
console.log('第二次暂停的结果为:', result2);
console.log('async函数执行结束');
} catch (error) {
console.log('async函数执行出错,错误为:', error);
}
}
myAsyncFunction();
for/async-await
在for循环中使用async/await需要注意以下几点:
- for循环中的异步操作必须是互相独立的,不能有依赖关系,否则会出现意想不到的结果。
- 可以使用
Promise.all()
方法将所有的异步操作包装成一个Promise对象,然后使用await等待所有异步操作完成。 - 在for循环中使用await时,需要将异步操作放在try/catch语句块中,以便捕获异步操作中的错误。
- 在for循环中使用let定义循环变量,避免变量作用域的问题。
以下是一个使用async/await实现for循环的示例代码:
```javascript
function P(i){
console.log(i)
return new Promise((resolve)=>{
setTimeout(() => {
resolve(i+2)
}, 1000);
})
}
async function myAsyncFunction() {
console.log('开始执行async函数');
try {
const arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
const result = await P(arr[i]);
console.log(`第${i + 1}次异步操作的结果为:`, result);
}
console.log('async函数执行结束');
} catch (error) {
console.log('async函数执行出错,错误为:', error);
}
}
myAsyncFunction();
/* 输出:
开始执行async函数
1
第1次异步操作的结果为: 3
2
第2次异步操作的结果为: 4
3
第3次异步操作的结果为: 5
async函数执行结束*/
```