JavaScript异步编程:Promise、async&await与Generator

2024-07-04 23:30:51 浏览数 (4)

Promise、async/await与Generator 是什么?它们有什么区别?

Promise 是 JavaScript 中用于处理异步操作的一种解决方案,它提供了一种更简洁、更清晰的方式来处理异步操作的结果。Promise 有三种状态:pending(进行中)、fulfilled(已完成,成功)和 rejected(已完成,失败)。Promise 的核心概念是链式调用,通过 .then() 方法处理成功(fulfilled)的结果,或者通过 .catch() 方法处理失败(rejected)的结果。

Async/Await

Async/await 是基于 Promise 的高级异步编程语法,它使得异步代码看起来更像是同步代码。使用 async 关键字定义一个函数,该函数内部可以使用 await 关键字等待 Promise 的结果。当遇到 await 时,函数会暂停执行,直到 Promise 被解析成功或失败。成功时返回 Promise 的值,失败时返回 Promise 的错误。这使得代码更易于阅读和理解,因为不需要显式地处理回调函数。

Generator

Generator函数是ES6引入的一种特殊函数,允许你编写出可以暂停执行并稍后继续执行的函数。Generator 函数使用 function* 关键字定义,内部使用 yield 关键字来暂停执行并返回一个值。当调用 Generator 函数时,它会返回一个迭代器对象,这个迭代器对象可以使用 next() 方法来继续执行 Generator 函数,直到所有 yield 表达式执行完毕或遇到 return 语句。

实战用法

Promise

Promise的基本用法

代码语言:js复制
const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched successfully');
    }, 1000);
  });
};

fetchData()
  .then(data => {
    console.log(data); 
  })
  .catch(error => {
    console.error(error);
  });

Promise链

Promise链允许 按顺序执行多个异步操作:

代码语言:js复制
const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched successfully');
    }, 1000);
  });
};

const processData = data => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`Processed ${data}`);
    }, 1000);
  });
};

fetchData()
  .then(data => processData(data))
  .then(processedData => {
    console.log(processedData);  successfully'
  })
  .catch(error => {
    console.error(error);
  });

Promise并发执行

代码语言:js复制
const fetchData1 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data1 fetched successfully');
    }, 1000);
  });
};

const fetchData2 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data2 fetched successfully');
    }, 1000);
  });
};
const main = async () => {
  try {
    const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
    console.log(data1, data2); // 'Data1 fetched successfully' 'Data2 fetched successfully'
  } catch (error) {
    console.error(error);
  }
};

async/await

async/await的基本用法

代码语言:js复制
const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched successfully');
    }, 1000);
  });
};

const processData = data => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`Processed ${data}`);
    }, 1000);
  });
};

const main = async () => {
  try {
    const data = await fetchData();
    const processedData = await processData(data);
    console.log(processedData); // 'Processed Data fetched successfully'
  } catch (error) {
    console.error(error);
  }
};

Generator

Generator的基本用法

  • 注:yield 是Generator函数中的一个关键字,它的作用是在每次函数暂停执行时返回一个值。yield表达式后面可以跟一个表达式,该表达式的值就是每次调用next()方法时返回的值。
  • 注:function* () 定义的是一个生成器函数(Generator Function)
代码语言:js复制
function* fetchDataGenerator() {
  yield new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched successfully');
    }, 1000);
  });
}

const gen = fetchDataGenerator();
const promise = gen.next().value;

promise.then(data => {
  console.log(data); // 'Data fetched successfully'
});

结合Promise和Generator

代码语言:js复制
function run(generatorFn) {
  const gen = generatorFn();

  function handle(result) {
    if (result.done) return Promise.resolve(result.value);

    return Promise.resolve(result.value)
      .then(res => handle(gen.next(res)))
      .catch(err => gen.throw(err));
  }

  return handle(gen.next());
}

function* fetchDataGenerator() {
  const data = yield new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched successfully');
    }, 1000);
  });

  console.log(data); // 'Data fetched successfully'
}

run(fetchDataGenerator);

至于在实际开发中应该怎么用,可以考虑实际场景来选择,因为这三种方法各有的优缺点,下面总结一下,可以根据每种方法的特点择优选择使用。

  • Promise提供了一种标准化的方式来处理异步操作的结果。可以方便地进行链式操作和组合多个异步操作。但容易出现回调地狱,导致代码结构复杂
  • async/await呢,就是基于 Promise 的语法糖,它允许你以同步的方式编写异步代码,极大地提高了异步代码的可读性和可维护性。错误处理更简单和直观。但就是不支持在普通函数中使用(函数前要加async标识),
  • Generator 则是用于创建迭代器的工具,允许在函数执行过程中暂停和恢复执行,适用于需要分批处理大量数据或需要在多个步骤间暂停执行的场景。且不如 async/await 那样直观,而且语法相对复杂,理解和使用成本较高。错误处理不够直观和简洁。

0 人点赞