下面是对 ES6 async函数的整理,希望可以帮助到有需要的小伙伴~
文章目录
async函数是什么
ECMAScript 2017规范引入了async函数,该函数的主要目的是简化使用Promise异步调用的操作,并对一组Promise执行某些操作。
Promise类似于结构化回调
async、await类似于组合生成器和Promises。
await
操作符用于等待一个Promise 对象。它只能在异步函数 async function 中使用
function resolveAfter2Seconds() {
return new Promise(resolve => {
setTimeout(()=>{
resolve('resolved');
},2000);
})
}
async function asyncCall() {
console.log("calling"); // calling
// 暂停当前asyncCall()函数的执行,等待Promise处理完成后再执行asyncCall()函数
var result = await resolveAfter2Seconds();
console.log(result); // resolved
}
asyncCall();
异步函数声明式
异步函数声明式用于定义一个返回Promise对象的异步函数。
异步函数是指通过事件循环异步执行的函数,它会通过一个隐式的Promise返回其结果。
异步函数的语法和结构与同步函数比较像。
async function name([param[, param[, ... param]ll) { statements }
- name:函数名称
- param:要传递给函数的参数的名称。
- statements:表示函数体语句。
异步函数表达式
步函数表达式用于在表达式中定义异步函数。
let name = async function([param1[, param2[ .., paramN]]]) { statements }
- name:表示函数名称。
- pacam:要传递给函数的参数的名称。
- statements:表示函数体语句。
异步函数表达式与异步函数语句声明式的区别:
于异步函数表达式可以省略函数名称来创建一个匿名函数。
返回Promise对象
async函数返回一个Promise对象
async函数内部return语句返回的值,会成为then方法回调函数的参数。
实例1:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JPVf9Xvg-1608908797743)(es6/async1.png)]
实例2:
async function f() {
return "hello world";
}
// f().then(v=>console.log(v)); // hello world
// 等同于
f().then(
function (v) {
console.log(v); // hello world
}
)
// 上述异步函数async function中没有await表达式,因为异步函数会先创建Promise对象,然后再执行
注意:
上述异步函数async function中没有await表达式,因为异步函数会先创建Promise对象,然后再执行
await表达式
await表达式用于等待一个Promise对象,它只能在异步函数中使用。
[return .value] = await expression;
-
expression:一个Promise对象或者任何要等待的值。
-
return…alue
- 如果等待的是Promise对象,返回Promise对象的处理结果(成功或失败)。
- 如果等待的不是Promise 对象,则返回该值本身。
function createPromise(){
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve("执行成功");
},200);
});
}
async function myAsync() {
console.log("当前异步函数被调用");
var result = await createPromise();
console.log("Promise对象执行的结果:" + result);
}
myAsync(); // 调用异步函数
await处理错误
为了防止报错,使用try…catch语句
function createPromise(){
return new Promise((resolve,reject) => {
setTimeout(() => {
reject("执行失败");
},200);
});
}
async function myAsync() {
console.log("当前异步函数被调用"); // 当前异步函数被调用
try {
// 执行后会出错的语句
var result = await createPromise();
} catch(e) {
// 提示错误的语句
console.log("Promise对象执行的结果:" + e); // Promise对象执行的结果:执行失败
}
}
myAsync(); // 调用异步函数
async函数执行一组Promise
一组Promise对象的执行顺序只与async函数中await的顺序有关。
let promise1 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("one");
},300);
});
let promise2 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("two");
},200);
});
let promise3 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("three");
},100);
});
async function myAsync() {
let result1 = await promise1;
console.log(result1);
let result2 = await promise2;
console.log(result2);
let result3 = await promise3;
console.log(result3);
}
myAsync();
// Promise对象执行的顺序与设置的延迟时间没有关系,Promise对象执行的顺序只与async函数中的顺序有关
注意事项
使用try…catch语句
await命令后面的Promise 对象,运行结果可能是rejected,有2种处理错误的方法
- try…catch语句
- Promise的catch语句
实例:
function fun() {
return new Promise((resolve,reject) => {
reject("执行失败");
})
}
// try...catch处理错误
async function myAsync1() {
try {
await fun();
}catch (e) {
console.log(e);
}
}
myAsync1(); // 执行失败
// catch处理错误
async function myAsync2() {
await fun().catch(function (err) {
console.log(err);
})
}
myAsync2(); // 执行失败
多个await同时触发
多个await表达式后面的异步操作,如果不存在继发关系,最好让它们同时触发。
let promise1 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("one");
},300);
});
let promise2 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("two");
},200);
});
let promise3 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("three");
},100);
});
// promise1,promise2,promise3依次独立的异步操作
/*async function myAsync() {
let result1 = await promise1;
console.log(result1);
let result2 = await promise2;
console.log(result2);
let result3 = await promise3;
console.log(result3);
}
myAsync();*/
// Promise对象执行的顺序与设置的延迟时间没有关系,Promise对象执行的顺序只与async函数中的顺序有关
// promise1,promise2,promise3同时执行异步操作
async function myAsync3() {
let [result1,result2,result3] = await Promise.all([promise1,promise2,promise3]);
console.log(result1,result2,result3)
}
myAsync3(); // one two three
promise1,promise2,promise3是3个独立的异步操作(即互不依赖),被写成继发关系一个一个的进行异步操作是比较耗时间的,可以让promise1,promise2,promise3同时触发,同时进行异步操作(同时触发的条件:promise1,promise2,promise3按顺序执行)。
await表达式的限制
await表达式只能用在async函数之中,如果用在普通函数,就会报错。
async function f1() {
let docs = [{},{},{}];
// 报错
docs.forEach(function (doc) {
await db.post(doc); // SyntaxError: await is only valid in async function 翻译:SyntaxError: await只在异步函数中有效
})
}
Symbol
ECMAScript 6新增了第六种原始类型Symbol(符号)类型。
Symbol类型是唯一的并且是不可修改的,并且也可以用来作为Object 的 key 值。
Symbol类型的变量是通过调用Symbol()函数生成的:
Symbol([description])
- description:可选的字符串。Symbol的描述,可用于调试但不能访问Symbol本身。
注意:
由于Symbol类型是原始类型,是不能通过new Symbol()来创建对象的。
实例:
/*
ES5 的 5种原始类型
* string - String
* number - Number
* string - String
* undefined - Undefined
* null - Null
ES6 新增一种原始类型
Symbol
*/
let num = 100; // new Number()
let str = "软件学院"; // new String()
let boo = true;
/*
symbol类型是ES6新增的第六种原始类型
Symbol类型是唯一的并且是不可修
let symbol = Symbol()
原始类型是不能创建对象的
*/
let symbol = Symbol();
console.log(typeof symbol); // symbol 判断原始类型必须使用typeof
let symbol2 = Symbol("xxx");
console.log(symbol2); // Symbol(xxx)
let symbol3 = Symbol(5);
console.log(symbol3); // Symbol(5)
// 修改变量的值,而不是修改类型,Symblo是不能转为其它类型的
symbol3 = Symbol("yyy");
console.log(symbol3); // Symbol(yyy)
Symbol的注意事项
当使用Symbol值进行类型转换时需要注意一些事情:
- 尝试将一个symbol值转换为一个number值时,会抛出一个工ypeError错误。
- Object(symbol) == symnbol表达式的结果返回true。
- 阻止从一个symbol 值隐式地创建一个新的string类型的属性名。
Symbol的方法
-
Symbol.for()方法
该方法会根据给定的键key,从symbol注册表中查找指定的key。
- 如果找到了,则返回它。
- 如果没有找到,新建一个与该键关联的 symbol,并放入全局symbol注册表中。
Symbol.for(key);
-
一个字符串,作为symbol注册表中与某symbol关联的键。
-
Symbol.for()方法与Symbol()的不同:
- 用Symbol.for()方法创建的的symbol会被放人一个全局symbol注册表中
- 用Symbol()方法创建的的symbol不会被放人一个全局symbol注册表中
注册表是一个典型的键值对key : value集合
举例:
kye - 存储的方式
value - 当前安装的软件
-
Symbol.keyFor()方法
该方法用于获取symbol注册表中与某个symbol关联的键。
Symbol.keyFor(sym);
- sym:存储在symbol注册表中的某个symbol.
Symbol与for…in
Symbols 在 for…in迭代中不可枚举。
Object.getOwnPropertyNames()不会返回symbol对象的属性,但是可以使用Object.getOwnPropertySymbols()得到它们.
var obj = {};
// 如果Symbol作为对象的属性名,属性名是不可枚举的
obj[Symbol("a")] = "a";
obj[Symbol.for("b")] = "b";
obj["c"] = "c";
obj.d = "d";
for (var i in obj) {
console.log(i); // c d 用Symbol作为对象的属性名的a和b是没有办法被枚举的
}
end 结束啦~