回调函数与promise与async/await

仅个人回忆向,初学不是很懂写下来加深印象,也欢迎大佬进行讲解和补充

首先在JavaScript中,有两种常见的方法来实现异步函数:

1.使用回调函数(Callback):这是一种传统的方法,在异步操作完成后,通过调用一个回调函数来处理结果。

(个人理解:回调函数就是执行异步函数的东西,异步执行完了就调用"回调函数"来处理)

例如:

scss 复制代码
function fetchData(callback) {  
   setTimeout(function() {    
        const data = 'Async data';    
        callback(data);  
    }, 1000);
}
​function handleData(data) {
    console.log(data);
}​

fetchData(handleData);

在上面的例子中,fetchData函数模拟了一个异步操作,通过setTimeout函数模拟1秒后返回数据。handleData函数作为回调函数传递给fetchData函数,在异步操作完成后被调用来处理返回的数据。

2.使用Promise对象:Promise是ES6中引入的一种处理异步操作的机制。它可以更方便地处理异步操作的结果,并且可以链式调用多个异步操作。

(个人理解:promise用来解决回调地狱,链式调用(.then)错误处理(.catch)和更好的可读性)

  • Promise(承诺),给予调用者一个承诺,过一会返回数据给你,就可以创建一个promise对象
  • 当我们new一个promise,此时我们需要传递一个回调函数,这个函数为立即执行的,称之为(executor)
  • 这个回调函数,我们需要传入两个参数回调函数,reslove,reject(函数可以进行传参)
    • 当执行了 **reslove**函数,会回调promise对象的.then函数

    • 当执行了 **reject**函数,会回调promise对象的.catche函数

作者:一只ice

链接:juejin.cn/post/714430...

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

例如:

javascript 复制代码
function fetchData() {  
    return new Promise(function(resolve, reject) {    
        setTimeout(function() {      
            const data = 'Async data';      
            resolve(data);    
         }, 1000);  
     });
}
​fetchData().then(function(data) {  
console.log(data);
}).catch(function(error) {  
console.log(error);
});

在上面的例子中,fetchData函数返回一个Promise对象。在异步操作完成后,调用resolve方法来传递结果。通过调用then方法来处理成功的情况,调用catch方法来处理失败的情况。

这两种方法都可以实现异步函数,选择使用哪种方法取决于具体的需求和项目的要求。

3.async和await

使用 async/await 可以将上述代码重写为以下形式:

javascript 复制代码
function fetchData() {  
    return new Promise(function(resolve, reject) {    
        setTimeout(function() {      
            const data = 'Async data';      
            resolve(data);    }, 1000);  
        });
}​
async function main() {  
    try {    
        const data = await fetchData();    
        console.log(data);  
    } catch (error) {    
        console.log(error);  
    }
}​
main();

在上述代码中,fetchData 函数返回一个 Promise 对象,并使用 setTimeout 模拟一个异步操作。在 main 函数中,我们使用 await 关键字来等待 fetchData 函数返回的 Promise 对象。当异步操作完成时,我们可以访问解决值并打印到控制台。如果异步操作失败,我们可以使用 try-catch 块来捕获错误并打印到控制台。

个人提问环节

1.使用await关键字可以使异步操作看起来更像同步操作,但它并不会阻塞整个程序的执行,举个例子.

当使用await关键字等待一个异步操作完成时,JavaScript引擎会继续执行其他可以执行的代码。下面是一个简单的例子来说明这一点:

javascript 复制代码
async function fetchData() { 
    console.log("Start fetching data"); 

    // 模拟一个异步操作,例如发送HTTP请求 
    await new Promise(resolve => setTimeout(resolve, 2000)); 
    console.log("Data fetched"); 
} 
console.log("Before calling fetchData"); 
fetchData(); 
console.log("After calling fetchData");

在这个例子中,我们定义了一个名为fetchData的异步函数。在函数内部,我们使用await关键字等待一个模拟的异步操作,即一个2秒钟的延迟。在异步操作完成之前,我们在控制台输出"Start fetching data"。然后,我们在控制台输出"After calling fetchData"。 当我们运行这段代码时,输出将会是:

kotlin 复制代码
Before calling fetchData
Start fetching data 
After calling fetchData 
Data fetched

从输出结果可以看出,在调用fetchData函数之后,控制台会立即输出"After calling fetchData",而不会等待异步操作完成。然后,在异步操作完成后,控制台输出"Data fetched"。 这个例子说明了使用await关键字时,虽然函数的执行被暂停等待异步操作完成,但整个程序的执行并没有被阻塞,它可以继续执行其他可以执行的代码。

2.promise相对于用回调函数的区别

Promise 是一种用于处理异步操作的编程模式,相对于使用回调函数,它具有以下几个区别:

  1. 可链式调用:Promise 提供了 `.then()` 方法,使得可以链式调用多个异步操作。这样可以避免回调地狱(callback hell)的问题,使得代码更加清晰易读。

  2. 错误处理:Promise 提供了 `.catch()` 方法,用于捕获和处理异步操作中的错误。这样可以集中处理错误,而不需要在每个回调函数中进行错误检查和处理。

  3. 更好的可读性:Promise 使用 `.then()` 和 `.catch()` 方法来处理异步操作的结果,使得代码的逻辑更加清晰和易于理解。

  4. 更好的错误追踪:Promise 可以捕获和跟踪异步操作中的错误,并将错误信息传递给 `.catch()` 方法。这样可以更容易地追踪错误的来源和调试代码。

  5. 更好的组合和复用性:Promise 可以通过 `.then()` 方法将多个异步操作链接在一起,形成一个操作序列。这样可以更方便地组合和复用异步操作。

总的来说,Promise 提供了一种更优雅和可读性更高的方式来处理异步操作。它能够减少回调地狱的问题,提供更好的错误处理和追踪机制,并提供更好的组合和复用性。

3.async/await也没比promise好啊,用async还要用trycatch获取错误,感觉比promise更麻烦

使用 async/awaittry-catch 的主要优势在于代码的可读性和可维护性。它们使异步代码看起来更像是同步代码,使得逻辑更加清晰和直观。

使用 async/await 可以避免回调地狱(callback hell)的问题,使异步代码更易于编写和理解。通过在异步操作前使用 await 关键字,代码可以暂停执行,直到异步操作完成并返回结果。这使得异步操作的处理更加直观和线性。

使用 try-catch 可以更容易地捕获和处理异步操作中的错误。在 try 块中执行异步操作,如果操作失败,则会抛出一个错误。然后可以在 catch 块中捕获该错误,并执行相应的错误处理逻辑。

尽管在某些情况下使用 async/awaittry-catch 可能会增加一些额外的代码,但它们提供了更好的代码结构和错误处理机制,使得代码更加健壮和可维护。

当然,选择使用 async/await 还是 Promise 取决于个人偏好和项目需求。有些情况下,使用 Promise 可能更适合简单的异步操作。但对于复杂的异步操作和更清晰的代码结构,async/awaittry-catch 是更好的选择。

4.用async/await时都要用到trycatch吗

在使用 async/await 时,并不是每个异步操作都需要使用 try-catch 块来捕获错误。try-catch 主要用于捕获可能发生的异常并进行错误处理。

在使用 async/await 时,可以根据需要决定是否使用 try-catch 块来捕获错误。以下是一些常见的情况:

  1. 如果您希望在发生错误时执行特定的错误处理逻辑,可以使用 try-catch 块来捕获错误并在 catch 块中处理它们。

    async function main() {

    try {

    const data = await fetchData();

    console.log(data);

    } catch (error) {

    console.log('An error occurred:', error);

    // 执行错误处理逻辑

    } }

  2. 如果您希望让错误向上传递到调用 main 函数的地方进行处理,可以在调用 main 函数的地方使用 try-catch 块来捕获错误。

javascript 复制代码
async function main() {  
    const data = await fetchData();  
    console.log(data);
}​
try {  
    main();
} catch (error) {  
    console.log('An error occurred:', error);  
    // 执行错误处理逻辑
}

3.如果您不需要特定的错误处理逻辑,并且希望让错误向上传递到调用 main 函数的地方进行处理,可以省略 try-catch 块。

javascript 复制代码
async function main() {  
    const data = await fetchData();  
    console.log(data);
}​
main().catch(error => {  
    console.log('An error occurred:', error);  
    // 执行错误处理逻辑
});

总之,使用 try-catch 块来捕获错误取决于您的需求和代码结构。在某些情况下,您可能希望在异步操作的特定位置进行错误处理,而在其他情况下,您可能希望将错误向上传递到调用函数的地方进行处理。

结语

暂时先写到这么多,一时接收这么多昏昏沉沉的,大概是理解了,但是用还不好说哈哈.

相关推荐
腾讯TNTWeb前端团队38 分钟前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰4 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪4 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪4 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy5 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom6 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom6 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom6 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom6 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom6 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试