在 JavaScript 的异步编程中,Promise 和 async/await 是非常常见的两种方式。它们可以帮助我们简化异步代码的书写,但是在实际使用过程中,我们也会经常遇到一些坑,比如 Promise 的 then 函数链式调用,async 函数中的异常处理等等。本文介绍了一些常见的 Promise/async 的坑,并解决了它们,以此为指导,帮助读者更好地理解这两个工具。
Promise 的 then 函数链式调用
Promise 的 then 函数可以让我们在异步操作完成后进行回调,但是在使用它的过程中,我们会发现一个问题:如果需要进行多个异步操作,会导致 then 函数嵌套调用,代码变得非常难以维护。这就是所谓的 "回调地狱"。
为了解决这个问题,我们可以借助 Promise 的链式调用机制。链式调用可以让我们在每个 Promise 完成后,都能够返回一个新的 Promise 对象,然后可以继续调用下一个 then 函数。
// javascriptcn.com 代码示例 async function getUserInfo() { await fetch('/api/user') .then(response => response.json()) .then(user => { console.log(user); return fetch(`/api/user/${user.id}`); }) .then(response => response.json()) .then(userInfo => console.log(userInfo)); }
在上面的代码中,我们首先发起了一个 GET 请求,然后在响应函数中解析 JSON 数据。接着,我们使用 then 函数发送了第二个请求,并在响应处理函数中打印了结果。这样,我们就成功地使用链式调用完成了多次异步操作。
async 函数中的异常处理
在 async 函数中,如果出现了异常,我们可以使用 try/catch 语句来捕获它。比如我们要获取一个不存在的用户信息,可能会导致程序异常。
// javascriptcn.com 代码示例 async function getUserInfo(id) { try { const response = await fetch(`/api/user/${id}`); const userInfo = await response.json(); console.log(userInfo); } catch (error) { console.error(error); } }
当我们调用 getUserInfo 函数时,如果传入的用户 ID 不存在,就会在控制台中输出该异常对象。
Promise 超时控制
在开发中,我们可能遇到请求超时的情况,为了避免请求过长时间仍未响应的问题,我们可以使用 Promise.race 实现一个超时控制。
// javascriptcn.com 代码示例 function fetchWithTimeout(url, ms) { const controller = new AbortController(); const promise = fetch(url, { signal: controller.signal }); const timeout = new Promise((_, reject) => { setTimeout(() => { controller.abort(); reject(new Error(`Timeout after ${ms}ms.`)); }, ms); }); return Promise.race([promise, timeout]); } async function getUserInfo(id) { try { const response = await fetchWithTimeout(`/api/user/${id}`, 3000); const userInfo = await response.json(); console.log(userInfo); } catch (error) { console.error(error); } }
在上面的代码中,我们创建了一个 fetchWithTimeout 函数,使用了 AbortController API 取消请求,同时创建了一个超时 Promise 实例,如果请求时间超出了设定的 ms 值则触发取消请求并返回超时错误,最后使用 Promise.race 来控制 handle 和 timeout 谁先返回,从而实现超时控制的操作。
总结
本文介绍了 Promise/async 的一些常见坑,并提出了解决方案,其中 Promise 链式调用可以让我们避免出现嵌套的回调函数,async 函数中的异常处理可以让我们优雅地处理出现的异常,Promise 超时控制则可以让我们更好地控制异步请求的响应时间。通过本文的阐述,读者可以更好地理解和应用 Promise/async,避免在日常工作中遇到常见错误。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/654d9fcc7d4982a6eb70bb2c