promise用法,及结合async,await详解

本文深入探讨了JavaScript中Promise的基础知识及其与async/await的结合使用方式。讲解了Promise的状态变化、链式调用等问题,并对比了Promise与传统回调在解决异步编程中的优势与不足。同时,介绍了Promise.all和Promise.race的功能与应用场景。

promise,及结合async,await详解

在这里插入图片描述

1.promise基础

  1. promise 异步问题同步化解决方案,很多人说promise解决了回调地狱。我认为promise只是顺带解决回调地狱,不是解决回调地狱的最佳方案,因为promise要链式then方法,一旦多起来,又陷入了then地狱。真正解决回调地狱的是async,await,简洁明了(待会下面细讲)。
  2. promise 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败),一旦状态改变,就不会再变,任何时候都可以得到这个结果
 console.log('我是前面的');
const p = new Promise((resolve, reject) => {//同步---excutor执行器(同步执行)(包含resolve, reject)
    console.log('我是前面的Promise里面同步')
   let a = 1
    if (a == 1) {
        resolve('成功啦')
    } else {
        reject('失败啦')
    }
})
//这个链式操作不是解决回调地狱的最佳方案
p.then(res => {//then这里才是异步
    console.log('resolve结果=>',res);
},err=>{
    console.log('reject结果=>',err)
})
.catch(err => {
    console.log('与上面的reject报错有异曲同工之妙',err)
    //如果上面 reject报错了,这里就不会再执行了
})
.finally(() => {
  console.log('无论失败成功都执行finally')
})
 console.log('我是后面的');

看一下打印结果
在这里插入图片描述

这就是为什么说 new Promise里面的excutor执行器是同步的,异步的时候是在调用then方法的时候

2.promise.all(比如:有时候页面的数据不是一个接口返回的,有多个接口)

1.用多个异步任务并发运行,等待所有任务结果的完成才resolve
2.只要有一个reject,就直接输出reject

例如:

function getdata() {
    return new Promise((resolve, reject) => {
       resolve(data)
    })
}
function getdata2() {
    return new Promise((resolve, reject) => {
       resolve(data)
    })
}
Promise.all([//传Promise对象集合,如果不传返回[]空数组
    getdata(),
    getdata2(),
]).then(res => {
    console.log(res)
}, (err) => {
    console.log(err)
})

结果:
在这里插入图片描述

3.promise.race(比如:有时候页面的数据不是一个接口返回的,有多个接口)

1.谁先完成就返回那个promise的结果,不论是resolve reject,反正就是返回最快的。
2.可以测试资源或接口的响应速度,或请求超时等。

例如:

function loadimg() {
    return new Promise((resolve, reject) => {
        let img = new Image()
        img.onload = function () {
            resolve(img)
        }
        img.src = 'https://cdn.eso.org/images/publicationjpg/eso1242a.jpg'
    })
}
function timeout() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('图片请求超时')
        }, 1000)
    })
}
Promise.race([
    timeout(),
    loadimg(),
]).then(res => {
    console.log(res)//如果超过1s就打印 图片请求超时
}, (err) => {
    console.log(err)
})

4.async await( 解决回调地狱的最佳方案)

await 是一个操作符 有点等待的意思,等待promise对象产出结果的操作手段,功能是暂停async的执行,等待promise处理后的结果。假如promise处理结果是rejected,会抛出异常。

async的意思是当前这个异步函数demo与同一作用域下的程序是异步的关系(不理解的可以看下面效果图,先执行外部console.log,再打印 async demo()里面的)。

console.log('我是前面的');
function getdata() {
    return new Promise((resolve, reject) => {
       resolve(data)
    })
}
demo()
async function demo() {
    let data = await getdata() //肉眼效果类似于开始同步了,其实是在等待promise对象产出结果。
      console.log(data)//去掉await打印出来就是<pending>等待
     //不需要继续嵌套回调了,解决回调地狱
    
    let data2 = await getdata()
    console.log('data2',data2)
    console.log('async执行完后');
}
console.log('先打印')
//async 函数是通过一个隐式的promise返回pending状态
// console.log(demo())  //结果为pending

结果:
在这里插入图片描述

<think>首先,用户的问题是:“我想理解JavaScript中Promise、then、asyncawait用法和原理 请问JavaScript Promise对象及then方法和async/await语法详解”。这是一个关于JavaScript异步编程的核心概念的问题。 根据系统级指令: - 所有行内数学表达式必须使用$...$格式。但在这个问题中,没有数学表达式,所以可能不需要。 - 独立公式必须使用$$...$$格式并单独成段。同样,这里可能没有数学公式。 - LaTeX语法正确:确保如果使用数学表达式时正确。 - 使用中文回答:整个回答必须用中文。 - 生成相关问题:在回答结束后,添加相关问题。 - 回答中引用的段落末尾自然地添加引用标识:例如[^1]。用户提供了三个引用:[^1], [^2], [^3],这些是关于JavaScript异步编程的参考。我需要自然地融入这些引用。 用户可见层指令: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 参考用户提供的引用: - [^1]: JavaScript异步编程:Promises与async/await详解。强调Promises和async/await的清晰性和性能提升。 - [^2]: JavaScript 异步编程之 PromiseAsync/Await 详解。强调它们解决了回调函数的缺点,使代码更优雅。 - [^3]: PromiseAsync/Await 详解。解释了async函数返回Promise对象,await的行为,以及一个例子。 回答结构: - 逐步解释:Promise对象、then方法、async函数、await关键字。 - 确保逻辑清晰,从基础到高级。 - 融入引用:在相关段落末尾添加引用标识。 大纲回答: 1. **介绍JavaScript异步编程的背景**:解释为什么需要异步编程,如避免阻塞UI。 2. **Promise对象详解**: - 什么是Promise:一个表示异步操作最终完成或失败的对象。 - 状态:pending, fulfilled, rejected。 - 创建Promise:使用new Promise(executor)。 3. **then方法**: - 如何用then处理成功和失败:then(onFulfilled, onRejected)。 - 链式调用:then返回新的Promise。 4. **asyncawait**: - async函数:总是返回一个Promise。 - await关键字:暂停async函数的执行,等待Promise解决。 - 例子:如引用[^3]中的例子。 5. **原理**:解释事件循环、微任务队列等(保持简单)。 6. **总结和优点**:引用[^1]和[^2]强调代码清晰和性能。 7. **生成相关问题**:在最后添加。 确保回答真实可靠:基于我的知识,PromiseES6引入的,async/awaitES7引入的。 用中文回答:所有内容用中文写。 添加引用: - 在解释完关键点后,自然地添加引用标识。例如: - 在讨论Promises的优点时,添加[^1]。 - 在解释async/await时,添加[^3]。 相关问题生成: - 根据系统指令,在回答结束后添加“§§相关问题§§”部分。 - 生成2-3个相关问题,如: 1. Promise的常见错误有哪些? 2. async/await如何处理错误? 3. 如何将回调函数转换为Promise? 完整结构: - 开头:介绍问题。 - 主体:分节解释。 - 结尾:总结。 - 相关问题。</think>### JavaScript Promise对象及then方法和async/await语法详解 JavaScript中的异步编程是处理耗时操作(如网络请求或文件读写)的关键,避免阻塞主线程。传统回调函数会导致“回调地狱”(Callback Hell),代码难以维护。ES6引入Promise对象,ES7添加async/await语法,使异步代码更简洁、可读。下面我将逐步解释其用法和原理,确保内容清晰可靠。 #### 1. **Promise对象:基础概念** Promise是一个表示异步操作最终结果的对象。它有三种状态: - **pending**:初始状态,操作未完成。 - **fulfilled**:操作成功完成。 - **rejected**:操作失败。 创建Promise使用`new Promise(executor)`语法,其中`executor`是一个函数,接收两个参数:`resolve`(用于成功时)和`reject`(用于失败时)。例如: ```javascript const myPromise = new Promise((resolve, reject) => { setTimeout(() => { const success = true; // 模拟操作结果 if (success) { resolve("操作成功!"); // 状态变为fulfilled } else { reject("操作失败!"); // 状态变为rejected } }, 1000); }); ``` Promise的核心优势是它封装了异步逻辑,并提供链式处理,避免了嵌套回调[^1]。 #### 2. **then方法:处理Promise结果** `then`方法是Promise的核心,用于处理异步操作的成功或失败结果。它接收两个可选的回调函数: - 第一个函数处理`fulfilled`状态(成功)。 - 第二个函数处理`rejected`状态(失败)。 语法:`promise.then(onFulfilled, onRejected)`。`then`方法本身返回一个新的Promise,支持链式调用。例如: ```javascript myPromise .then( (result) => { console.log(result); // 输出:"操作成功!" return "新数据"; // 返回新值,用于下一个then }, (error) => { console.error(error); // 处理错误 throw new Error("处理失败"); // 抛出错误,触发catch } ) .then((newResult) => { console.log(newResult); // 输出:"新数据" }) .catch((error) => { console.error("捕获错误:", error); // 统一处理链中任何错误 }); ``` 原理:`then`将回调函数加入微任务队列(Microtask Queue),事件循环(Event Loop)在同步代码执行完后处理这些任务,确保异步顺序执行[^2]。链式调用通过返回新Promise实现,每个`then`等待前一个完成。 #### 3. **asyncawait:简化异步代码** `async`和`await`是基于Promise的语法糖,使异步代码看起来像同步代码,提升可读性。 - **async函数**:声明一个函数为异步函数,它总是返回一个Promise对象。如果函数返回值不是Promise,会自动包装成fulfilled状态的Promise。 ```javascript async function fetchData() { return "数据获取成功"; // 等价于 Promise.resolve("数据获取成功") } ``` - **await关键字**:只能在async函数内部使用。它暂停async函数的执行,等待一个Promise解决(fulfilled或rejected),然后恢复执行并返回结果。如果Promise rejected,await会抛出错误。 ```javascript async function getUser() { try { const response = await fetch('https://api.example.com/user'); // 等待网络请求完成 const data = await response.json(); // 等待JSON解析 console.log(data); return data; } catch (error) { console.error("请求失败:", error); // 捕获错误 } } getUser(); // 调用async函数,返回Promise ``` 原理:`await`本质上是语法糖,底层转换为`then`调用。当遇到`await`时,JavaScript引擎将后续代码包装为微任务,等待Promise解决后执行。这避免了回调嵌套,使代码更线性[^3]。 引用[^3]中的例子: ```javascript async function async1() { console.log('async1 start'); await async2(); console.log('async1 end'); } async function async2() { console.log('async2'); } console.log('script start'); async1(); console.log('script end'); // 输出顺序:script start -> async1 start -> async2 -> script end -> async1 end ``` 解释:`await async2()`暂停`async1`的执行,先执行同步代码(`script end`),然后当`async2`完成时恢复`async1`。 #### 4. **整体原理和优势** - **事件循环机制**:JavaScript是单线程语言,通过事件循环处理异步任务。Promiseasync/await利用微任务队列,优先于宏任务(如setTimeout)执行,确保高效性。 - **错误处理**:`then`的第二个参数或`catch`方法处理错误;async函数中可用`try/catch`捕获await错误。 - **优点**: - **代码清晰**:async/await消除回调嵌套,使逻辑更直观。 - **性能提升**:减少不必要的上下文切换,优化资源使用[^1]。 - **错误传播**:链式Promiseasync函数能统一处理错误,避免遗漏[^2]。 总结:Promise异步编程的基础,`then`提供链式处理,而async/await以同步风格简化代码。掌握这些工具能显著提升JavaScript应用的质量和可维护性[^1][^2]。如果您有具体代码场景,我可以进一步分析!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

web前端小龚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值