通过提问的方式搞懂 Promise 和 async/await

Promise是JavaScript处理异步操作的对象,有pending、fulfilled和rejected三种状态。通过then和catch方法处理Promise状态变化。async/await是基于Promise的异步语法,使代码更易读。async函数中使用await等待Promise结果,try...catch语句处理错误。这两个特性简化了JavaScript的异步编程。
摘要由CSDN通过智能技术生成

一、什么是Promise

        Promise 是 JavaScript 中用于处理异步操作的一种对象。它有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)。

        Promise 构造函数接收一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。resolve 用于将 Promise 对象的状态从 pending 改变为 fulfilled,reject 用于将 Promise 对象的状态从 pending 改变为 rejected。

        你可以使用 then 方法来处理 Promise 对象状态改变后的结果。then 方法可以接收两个回调函数作为参数,第一个回调函数是 Promise 对象的状态改变为 resolved 时调用,第二个回调函数是 Promise 对象的状态变为 rejected 时调用。其中第二个参数可以省略。你还可以使用 catch 方法来处理 Promise 对象被 reject 的情况。catch 方法相当于最近的 then 方法的第二个参数,指向 reject 的回调函数。

二、用两个简单的例子来说明 Promise 的用法

let myPromise = new Promise((resolve, reject) => {
    let x = 1;
    if (x === 1) {
        resolve('成功');
    } else {
        reject('失败');
    }
});

myPromise.then(
    (value) => { console.log(value); },
    (error) => { console.log(error); }
);

        在这个例子中,我们创建了一个新的 Promise 对象 myPromise。在 Promise 构造函数中,我们传入了一个函数作为参数。这个函数有两个参数:resolve 和 reject。在这个函数中,我们定义了一个变量 x 并赋值为 1。然后我们使用 if 语句来判断 x 的值是否等于 1。如果等于,则调用 resolve 函数并传入 '成功' 作为参数;否则调用 reject 函数并传入 '失败' 作为参数。

        接下来,我们使用 then 方法来处理 Promise 对象状态改变后的结果。then 方法接收两个回调函数作为参数。第一个回调函数是 Promise 对象的状态改变为 resolved 时调用,第二个回调函数是 Promise 对象的状态变为 rejected 时调用。在这个例子中,当运行到 then 方法时,由于之前已经调用了 resolve 函数并传入 '成功' 作为参数,所以 then 方法中的第一个回调函数会被执行,并打印出 '成功'

function getData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            let data = 'some data';
            resolve(data);
        }, 1000);
    });
}

getData().then((data) => {
    console.log(data);
});

        假设你有一个函数 getData,它需要一段时间来获取数据。在这个例子中,getData 函数返回了一个新的 Promise 对象。在 Promise 构造函数中,我们传入了一个函数作为参数。这个函数有两个参数:resolve 和 reject。在这个函数中,我们使用 setTimeout 函数来模拟获取数据需要一段时间的情况。当 setTimeout 函数执行完毕后,我们调用 resolve 函数并传入 'some data' 作为参数。接下来,我们调用 getData() 函数并使用 then 方法来处理返回的 Promise 对象状态改变后的结果。then 方法接收一个回调函数作为参数。当 Promise 对象的状态改变为 resolved 时,这个回调函数会被执行,并打印出 'some data'

 三、再说说catch 方法

        catch 方法用于处理 Promise 对象被 reject 的情况。它相当于最近的 then 方法的第二个参数,指向 reject 的回调函数。下面是一个简单的例子来说明 catch 方法的用法:

let myPromise = new Promise((resolve, reject) => {
    let x = 0;
    if (x === 1) {
        resolve('成功');
    } else {
        reject('失败');
    }
});

myPromise.then(
    (value) => { console.log(value); }
).catch(
    (error) => { console.log(error); }
);

        在这个例子中,我们创建了一个新的 Promise 对象 myPromise。在 Promise 构造函数中,我们传入了一个函数作为参数。这个函数有两个参数:resolve 和 reject。在这个函数中,我们定义了一个变量 x 并赋值为 0。然后我们使用 if 语句来判断 x 的值是否等于 1。如果等于,则调用 resolve 函数并传入 '成功' 作为参数;否则调用 reject 函数并传入 '失败' 作为参数。

        接下来,我们使用 then 方法和 catch 方法来处理 Promise 对象状态改变后的结果。then 方法接收一个回调函数作为参数,当 Promise 对象的状态改变为 resolved 时,这个回调函数会被执行。catch 方法也接收一个回调函数作为参数,当 Promise 对象的状态改变为 rejected 时,这个回调函数会被执行。当运行到 catch 方法时,由于之前已经调用了 reject 函数并传入 '失败' 作为参数,所以 catch 方法中的回调函数会被执行,并打印出 '失败'

四、那catch和then中的第二个参数有啥区别?它们可以同时存在吗?

        catch 方法和 then 方法的第二个参数都用于处理 Promise 对象被 reject 的情况。它们的区别在于:

  • catch 方法相当于最近的 then 方法的第二个参数,指向 reject 的回调函数。
  • catch 方法可以捕获前面 then 方法执行中抛出的异常,而 then 方法的第二个参数只能捕获前面 Promise 对象被 reject 的情况。

        下面是一个简单的例子来说明这两者之间的区别:

let myPromise = new Promise((resolve, reject) => {
    let x = 0;
    if (x === 1) {
        resolve('成功');
    } else {
        reject('失败');
    }
});

myPromise.then(
    (value) => { throw new Error('错误'); },
    (error) => { console.log('then: ' + error); }
).catch(
    (error) => { console.log('catch: ' + error); }
);

        在这个例子中,我们创建了一个新的 Promise 对象 myPromise。在 Promise 构造函数中,我们传入了一个函数作为参数。这个函数有两个参数:resolve 和 reject。在这个函数中,我们定义了一个变量 x 并赋值为 0。然后我们使用 if 语句来判断 x 的值是否等于 1。如果等于,则调用 resolve 函数并传入 '成功' 作为参数;否则调用 reject 函数并传入 '失败' 作为参数。

        接下来,我们使用 then 方法和 catch 方法来处理 Promise 对象状态改变后的结果。then 方法接收两个回调函数作为参数。第一个回调函数是 Promise 对象的状态改变为 resolved 时调用,第二个回调函数是 Promise 对象的状态变为 rejected 时调用。catch 方法也接收一个回调函数作为参数,当 Promise 对象的状态改变为 rejected 或者前面 then 方法执行中抛出异常时,这个回调函数会被执行当运行到 catch 方法时,由于之前已经抛出了异常 '错误' ,所以 catch 方法中的回调函数会被执行,并打印出 'catch: Error: 错误'

        所以,在同一条链上既可以使用 then 的第二个参数也可以使用 catch 来处理错误。但是建议使用 catch 来处理错误,因为它能够捕获更多类型的错误。

五、finally 方法如何使用?

        finally:无论 Promise 对象最终状态如何,都会执行的操作。以一个简单的例子来说明 finally 方法的用法:

let myPromise = new Promise((resolve, reject) => {
    let x = 0;
    if (x === 1) {
        resolve('成功');
    } else {
        reject('失败');
    }
});

myPromise.then(
    (value) => { console.log(value); }
).catch(
    (error) => { console.log(error); }
).finally(
    () => { console.log('完成'); }
);

        在这个例子中,我们创建了一个新的 Promise 对象 myPromise。在 Promise 构造函数中,我们传入了一个函数作为参数。这个函数有两个参数:resolve 和 reject。在这个函数中,我们定义了一个变量 x 并赋值为 0。然后我们使用 if 语句来判断 x 的值是否等于 1。如果等于,则调用 resolve 函数并传入 '成功' 作为参数;否则调用 reject 函数并传入 '失败' 作为参数。

        接下来,我们使用 then 方法、catch 方法和 finally 方法来处理 Promise 对象状态改变后的结果。then 方法接收一个回调函数作为参数,当 Promise 对象的状态改变为 resolved 时,这个回调函数会被执行。catch 方法也接收一个回调函数作为参数,当 Promise 对象的状态改变为 rejected 或者前面 then 方法执行中抛出异常时,这个回调函数会被执行。finally 方法也接收一个回调函数作为参数,在无论 Promise 对象最终状态如何时都会被执行。

        在这个例子中,当运行到 finally 方法时,无论之前发生了什么情况(即使之前抛出异常),finally 方法中的回调函数都会被执行,并打印出 '完成'

六、什么是async/await?

        async/await 是 JavaScript 中处理异步代码的一种现代语法,它使代码更简单易懂。它建立在 Promise 之上,这是 JavaScript 中处理异步代码的一个基本概念。async/await 使得编写看起来和表现得像同步代码的异步代码变得更容易。

        下面是一个简单的async/await示例,它演示了如何在异步函数中使用await关键字等待一个Promise完成:

async function example() {
  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("done!"), 1000)
  });

  let result = await promise; // 等待,直到promise返回结果

  console.log(result); // "done!"
}

example();

        在这个例子中,我们定义了一个名为example的异步函数。在函数体内,我们创建了一个新的Promise对象,并将其存储在变量promise中。这个Promise对象在1秒后使用resolve函数返回字符串"done!"。然后,我们使用await关键字等待这个Promise完成,并将结果存储在变量result中。最后,我们打印出获取到的结果。

七、如何处理async/await中的错误?

        在使用async/await时,可以使用try...catch语句来捕获并处理错误。下面是一个简单的示例:

async function fetchData() {
  try {
    const response = await fetch('https://some-api.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  } finally {
    console.log('Fetch completed');
  }
}

fetchData();

         在这个例子中,我们定义了一个名为 fetchData 的异步函数。它使了 try...catch...finally 语句来处理异步操作。在函数体内,我们使用try...catch语句来捕获可能发生的错误。如果在执行try块中的代码时发生错误,程序将跳转到catch块,并执行其中的代码。无论异步操作是否成功,都会执行 finally 块中的代码。

八、Promise 和  async await 的区别及应用场景

       async/await 和 Promise 都是用来处理异步编程的。async/await 是在 ES7 中引入的,相对于 ES6 中的 Promise 来说,写法更加优雅。当你需要异步像同步一样执行时,可以使用它们。例如,你需要等待一个异步方法执行完成后再继续执行其他操作。

       用一个简单的例子来说明 Promise 和 async/await 的区别:

        使用 Promise:

function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('Data fetched');
    }, 1000);
  });
}

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

        使用 async/await

async function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('Data fetched');
    }, 1000);
  });
}

async function main() {
  const data = await fetchData();
  console.log(data);
}

main();

        在这个例子中,我们定义了一个名为 fetchData 的函数,它返回一个 Promise 对象。在第一个例子中,我们使用了 then 方法来处理异步返回的数据。在第二个例子中,我们用了 async/await 来实现相同的功能。你可以看到,在使用 async/await 的情况下,代码更加简洁易读。Promise通过链式调用,直接在then中返回一个Promise来将异步操作串联起来,用catch来做错误处理。而async/await则直接在代码上顺序处理结果。

九、async/await使用时要注意什么?

        在使用async/await时,有几点需要注意。首先,await语法只能出现在通过async修饰的函数中,否则会报SyntaxError错误。此外,await后面的对象需要是一个Awaitable,或者实现了相关的协议

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值