前端开发之:异步I/O

promise

  1. Promise是一种用于处理异步操作的对象,它可以将异步操作的结果以回调函数的形式返回给调用者。
  2. Promise对象有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
  3. 当异步操作执行完毕后,Promise对象的状态会从pending变为fulfilled或rejected,然后调用对应的回调函数。
  4. 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

  1. Generator 函数是ES6引入的一种新的函数类型,可以通过yield关键字实现函数的暂停和恢复,从而实现异步编程。
  2. 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

  1. 本身不会返回任何值,返回值一直为 undefined
  2. 当下一个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函数的自动执行异步

  1. g函数的每个next() 的返回{value, done}value转换为一个Promise
  2. 然后监听 value.then(onFullFilled, onRejected)
  3. 分别在 onFullFilled 和 onRejected中判断并调用g.next()实现循环自动执行
  4. 并将上个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

  1. async/await是ES7引入的一种新的异步编程方式,它是基于Promise实现的语法糖,可以让异步代码看起来更像同步代码,更易于理解和维护。
  2. async函数返回一个Promise对象,可以使用then方法添加回调函数,也可以使用await关键字等待Promise对象的状态变更。
  3. async函数内部可以使用await关键字等待一个Promise对象的状态变更,await关键字后面的代码会被暂停执行,直到Promise对象的状态变为resolved或rejected。
  4. 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需要注意以下几点:

  1. for循环中的异步操作必须是互相独立的,不能有依赖关系,否则会出现意想不到的结果。
  2. 可以使用Promise.all()方法将所有的异步操作包装成一个Promise对象,然后使用await等待所有异步操作完成。
  3. 在for循环中使用await时,需要将异步操作放在try/catch语句块中,以便捕获异步操作中的错误。
  4. 在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函数执行结束*/

```

上一篇
下一篇