then(),关键字async和await
欢迎来到我的博客!
使用 Markdown 格式编写。
今天学到了什么
-
then(箭头函数)
then是一个方法,形参是一个函数,我这是在调用then这个方法
-
async和await
-
await详解
then()
这是一个非常容易混淆的知识点!你混淆了 “回调函数的返回值” 和 “then() 方法本身的返回值”。
注释里说的 // then()原地的结果是一个新的Promise对象 是完全正确的。
你可以这样理解:
-
then()方法本身永远都会返回一个新的 Promise 对象: 不管你在then()的回调函数内部写了什么,哪怕你什么都不写,p.then(...)这个表达式执行完后,原地留下的一定是一个全新的 Promise 对象(这也是为什么你能一直.then().then()链式调用的根本原因)。 -
你写的
return仅仅是用来决定这个“新 Promise”的最终结果是什么:- 如果你不写
return(默认返回undefined):then()返回的那个新 Promise 依然存在,只不过它的状态会自动变成成功(fulfilled),自带的数据是undefined。 - 如果你
return了一个普通字符串/数字:then()返回的新 Promise 状态变成成功,自带的数据是你 return 的字符串/数字。 - 如果你写了
return new Promise(...):then()返回的新 Promise 会被“替换”或“接管”。它会等待内部这个new Promise执行完毕,内部是成功它就跟着成功,内部是失败它就跟着失败。
- 如果你不写
验证一下:
你可以尝试把那个 return new Promise(...) 删掉或者注释掉,只保留 console.log(result),你会发现最后的 console.log(p2 === p) 依然是 false,而且你可以打印一下 console.log(p2),你会看到它依然是一个 Promise 对象,仅仅是它内部的 PromiseResult 变成了 undefined。
换句话说:没写 return 导致拿到 undefined 的是下一次 then() 里面接收的参数,而不是外层 then() 创造出来的对象。
async和await
是的,这完全是 JavaScript 的原生基本语法,属于 ES8(ECMAScript 2017)引入的标准。它没有任何魔法,也不需要借助第三方库,浏览器原生就支持。
它本质上是 Promise 的“语法糖”(换一种更甜、更舒服的写法),底层机制依然是你刚才学的 Promise。
async(异步的):写在function前面,把一个普通函数声明为“异步函数”。(顺带一提,被async修饰的函数执行后,无论里面写什么,一定会默认返回一个 Promise 对象)。await(等待):只能写在async函数的内部。它的作用就像一个暂停键。当代码执行到await axios(...)时,这个函数内部的代码会暂停往下走,死死盯住右边这个 Promise。直到它请求成功,await就会直接把成功拿到的数据(也就是原来.then(res => ...)里的那个res)剥离出来,赋值给左边的变量pObj,然后代码才继续往下走。
为什么要引入这种语法?
刚才你理解 .then() 和 return new Promise 时,是不是觉得传来传去、套来套去还是有点绕?
async / await 就是为了彻底消灭回调函数。它让你能够用极其直观的、从上到下一行一行的“同步代码”格式,来编写实际上是异步的代码。
await详解:axios返回的不是一个promise对象吗?那这个变量为什么是then函数中的res?
你的前半句理解得完全正确:axios(...) 本身执行完毕后,确实是返回了一个 Promise 对象。
但是,当你在一个 Promise 对象前面加上 await 关键字时,JS 引擎会帮你做一层“魔法转换”:
- 暂停与等待:
await会让当前这个async函数暂停往下执行,留在原地“死等”这个 Promise 对象的结果。 - 自动解包获取结果: 当这个 Promise 处于成功状态时,
await会自动把 Promise 里那个成功的数据提取出来(也就是你以前在.then(res => {...})里拿到的那个res),然后赋值给等号左边的变量pObj。
你可以把 await 想象成一个“吸星大法”或者“开箱器”:它专门负责把 Promise 盒子拆开,直接把里面的成功结果丢给你。
我们来做个直观的对比,这两种写法的最终目的完完全全是一样的:
以前的写法(用 then):
axios({url: 'http://hmajax.itheima.net/api/province'}) .then(pObj => { // 成功的结果赋值给了形参 pObj console.log(pObj) })现在的写法(用 async/await):
// await 直接把解析出来的成功结果,赋值给了变量 pObjconst pObj = await axios({url: 'http://hmajax.itheima.net/api/province'})console.log(pObj)总结:
这叫做**“语法糖”。因为天天写 .then().then().then() 嵌套回调函数太恶心了(回调地狱),所以 JS 官方发明了 await。它让你能用写同步代码的格式,去写异步代码**。它底层依然是 Promise 和 then,只是 JS 帮你在表面上把它精简成了等号赋值的样子。
赞助支持
如果这篇文章对你有帮助,欢迎赞助支持!
部分内容可能已过时