文章目录
- 背景
- 什么是Promise
- promise是用来解决什么问题的
- promise有三个状态
- js async/await
- async - 定义异步函数
- await - 暂停异步函数的执行
- 如何从then()方法的api请求中获取数据,以便在函数外部处理数据
- 工作中遇到常见问题总结
- await is only valid in async function
- 参考
背景
Promise 是一个 ECMAScript
6 提供的类,目的是更加优雅地书写复杂的异步任务。
ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等,而 ES2015 则是正式名称,特指该年发布的正式版本的语言标准。一般提到 ES6 的地方,一般是指 ES2015 标准,但有时也是泛指“下一代 JavaScript 语言”。
ECMAScript 当前的所有提案,可以在 TC39 的官方网站https://github.com/tc39/ecma262
查看。
什么是Promise
MDN 官网:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
w3schools官网:https://www.w3schools.com/Js/js_promise.asp
阮一峰的ECMAScript 6 入门: https://es6.ruanyifeng.com/#docs/promise
Promise 是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。promise有三种状态: pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行。
1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列
- promise 是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外)
- 并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据
- 代码风格,容易理解,便于维护
- 多个异步等待合并便于解决
new Promise(
function (resolve, reject) {
// 一段耗时的异步操作
resolve('成功') // 数据处理完成
// reject('失败') // 数据处理出错
}
).then(
(res) => {console.log(res)}, // 成功
(err) => {console.log(err)} // 失败
)
promise是用来解决什么问题的
promise是用来解决两个问题的:
- 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
- promise可以支持多个并发的请求,获取并发请求中的数据
- 这个promise可以解决异步的问题,本身不能说promise是异步的
处理异步请求,我们一般这样写
要求:先取得用户姓名,在根据姓名,取得用户的手机号
$.get('xxx.com/getUserName',function(data){
$.get('xxx.com/getMobile',{user:data.userName},function(data){
});
});
多个异步请求在一起,会出现嵌套深的情况,从而带来阅读和维护困难。
promise 本质上是分离了异步数据获取和业务逻辑,从而让开发人员能专注于一个事物,而不必同时考虑业务和数据。
promise有三个状态
1、pending[待定]初始状态
2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败
当promise状态发生改变,就会触发then()里的响应函数处理后续步骤;
promise状态一经改变,不会再变。
Promise对象的状态改变,只有两种可能:
- 从pending变为fulfilled
- 从pending变为rejected。
这两种情况只要发生,状态就凝固了,不会再变了。
最简单的实例:
new Promise(resolve => {
setTimeout(() => {
resolve('hello')
}, 2000)
}).then(res => {
console.log(res)
})
js async/await
异步神器Async-await介绍与填坑
參考URL: https://www.jianshu.com/p/e511be9c1280
async/await 是ES7中被提实现异步操作的技术,相对比较新。
async - 定义异步函数
async 译:异步,是 Generator 函数的语法糖。该函数会返回一个promise对象,可以使用then方法添加回调函数,如果在函数内直接 return,Async会通过Promise.resolve()将其封装成Promise()对象,也可以通过.then添加回调函数
async function timeout(){
return "helloworld";
}
console.log(timeout());
console.log("我在异步函数后面,会先执行谁呢");
// Promise { 'helloworld' }
// 我在异步函数后面,会先执行谁呢
作为一个关键字放在函数的前面,表示该函数是一个异步函数,意味着该函数的执行不会阻塞后面代码的执行 异步函数的调用跟普通函数一样。
可以看出执行顺序还是函数先执行,但是函数的返回结果是一个Promise对象,要获取Promise的返回值应该用then方法
async function timeout(){
return "helloworld";
}
timeout().then((result)=>{
console.log(result);
});
console.log("我在异步函数后面,会先执行谁呢");
// 我在异步函数后面,会先执行谁呢
// helloworld
此时先输出的就是后面的一串文字,说明异步函数的执行没有阻塞后面的代码执行。
async的内部实现原理就是如果该函数中有一个返回值,当调用该函数时,默认会在内部调用Promise.solve() 方法把它转化成一个Promise 对象作为返回,若函数内部抛出错误,则调用Promise.reject()返回一个Promise 对象
async function timeout1(flag){
if(flag){
return "hello world";
}else{
throw new Error("error!!");
}
}
console.log(timeout1(true));
console.log(timeout1(false));
// Promise {<resolved>: "hello world"}
// Promise {<rejected>: Error: error!!...}
既然async返回的是一个Promise 对象,那么Promise 的所有用法他都可以用,如Promise.catch捕获异常等。
await - 暂停异步函数的执行
深入理解await与async
参考URL: https://www.cnblogs.com/jsgoshu/p/11444404.html
与线程阻塞不同的是,await 的阻塞发生在 async 函数内部,可以理解为一个异步的阻塞。
await命令后面的 Promise 对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到。
- await的意思就是等待。它后面可以跟一个表达式。如果是值(如字符串、数字、普通对象等等)的话,返回值就是本身的值。
- 不过最常用的是后面跟一个promise对象。await会等待这个promise的状态由pending转为fulfilled或者rejected。在此期间它会阻塞,延迟执行await语句后面的语句。
await即等待,用于等待一个Promise对象。它只能在异步函数 async function中使用,否则会报错。
它的返回值不是Promise对象而是Promise对象处理之后的结果。
await表达式会暂停当前 async function的执行,等待Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function,若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。如果 await 操作符后的表达式的值不是一个 Promise,那么该值将被转换为一个已正常处理的 Promise。
如何从then()方法的api请求中获取数据,以便在函数外部处理数据
如何从then()方法的api请求中获取数据,以便在函数外部处理数据?
参考URL: https://cloud.tencent.com/developer/ask/sof/1086274
这应该在异步函数中完成。
工作中遇到常见问题总结
await is only valid in async function
const token = await hermez.CoordinatorAPI.getTokens()
运行报错:
SyntaxError: await is only valid in async function
问题分析:
这个错误的意思是await只能放到async函数内部,言下之意:
await必须放到函数里
函数必须有async修饰符
参考
[推荐-写的比较清晰]async/await
参考URL: https://www.jianshu.com/p/fb1da22f335d