promise
这里新构建了一个函数readSync包装了一下,让它返回一个Promise.
//json数据
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"sourceMap": true
},
"exclude": [
"node_modules"
]
}
function readData(){
return new Promise((resolve,reject)=>{
$.ajax({
url:'./tsconfig.json',
success:(res)=>{
resolve(res) //用resolve返回成功的res数据
},
error:(res)=>{
reject(res) //用reject返回失败的数据
}
})
})
}
readData()
.then(data => console.log(JSON.parse(data).compilerOptions.module)) //commonjs
.catch(reason => console.error(reason));
async/await语法糖
async-await是promise和generator的语法糖
简单来说:async-await 是建立在 promise机制之上的,并不能取代其地位。
最后借助es7给出的async/await语法糖,将让异步等待,变成同步.
function readData(){
return new Promise((resolve,reject)=>{
$.ajax({
url:'./tsconfig.json',
success:(res)=>{
resolve(res) //用resolve返回成功的res数据
},
error:(res)=>{
reject(res) //用reject返回失败的数据
}
})
})
}
async function readData2(){
let res = await readData();
console.log(JSON.parse(res).compilerOptions.module)
}
readData2() //commonjs
这里,有新增加了一个函数:readData2,借助async/await语法糖,这样就变成同步代码了.
.then()方法中的数据变成了返回值.
不过Prmoise中他的prototype中有一个all方法:
Promise.all(iter)
如果你在一个函数中有多个await,这个样子线程阻塞,很耗费时间,Promise.all方法,可以将多个await变成并行的去await.
async就相当于promise 而await就相当于 then
整个的内部是一样的只是表现的形式不一样了而已
需要注意的是async指定了函数 才能在那个函数里面写await
async 结合 promise使用
async function demo01() {
return 123;
}
demo01().then(val => {
console.log(val);// 123
});
若 async 定义的函数有返回值,return 123;相当于Promise.resolve(123),没有声明式的 return则相当于执行了Promise.resolve();
await
await 可以理解为是 async wait 的简写。await 必须出现在 async 函数内部,不能单独使用。
function notAsyncFunc() {
await Math.random();
}
notAsyncFunc();//Uncaught SyntaxError: Unexpected identifier
await 后面可以跟任何的JS 表达式。虽然说 await 可以等很多类型的东西,但是它最主要的意图是用来等待 Promise 对象的状态被 resolved。如果await的是 promise对象会造成异步函数停止执行并且等待 promise 的解决,如果等的是正常的表达式则立即执行。
function sleep(second){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('enough sleep~~~')
},second)
})
}
function normalFun(){
console.log('normalFun')
}
async function awaitDemo(){
await normalFun();
console.log('something, ~~');
let res = await sleep(2000)
console.log(res)
}
awaitDemo() //normalFun
//something, ~~
//enough sleep~~~
真实情况下的应用
情况一:reject 的处理
为了处理Promise.reject 的情况我们应该将代码块用 try catch 包裹一下
function sleep(){
return new Promise((resolve,reject)=>{
$.ajax({
url:'./tsconfig.json1', //地址故意写错
success:(res)=>{
resolve(res) //用resolve返回成功的res数据
},
error:(res)=>{
reject(res) //用reject返回失败的数据
}
})
})
}
async function asyncDemo() {
try{
let result = await sleep()
console.log("success-----",result)
}catch(err){
console.log("error---",err)
}
}
asyncDemo() //error--- {readyState: 4, getResponseHeader: ƒ, ...}
有了 try catch 之后我们就能够拿到 Promise.reject 回来的数据了。
情况二:有三个请求需要发生,第三个请求是依赖于第二个请求的解构第二个请求依赖于第一个请求的结果。
function sleep(second, param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(param);
}, second);
})
}
async function test() {
let result1 = await sleep(2000, 'req01');
let result2 = await sleep(1000, 'req02' + result1);
let result3 = await sleep(500, 'req03' + result2);
console.log(`
${result3}
${result2}
${result1}
`);
}
情况三:三个异步操作 相互没有关联 只是需要当请求都结束后将界面的 loading 清除掉即可
使用Promise.all()
function sleep() {
return new Promise((resolve,reject)=>{
$.ajax({
url:'./tsconfig.json',
success:(res)=>{
resolve(JSON.parse(res).compilerOptions.target) //用resolve返回成功的res数据
},
error:(res)=>{
reject(res) //用reject返回失败的数据
}
})
})
}
async function asyncDemo(){
let p1 = sleep();
let p2 = sleep();
let p3 = sleep();
let res = await Promise.all([p1,p2,p3]);
console.log('clear the loading~') //这样是错误的
}
asyncDemo()
情况四:await in for 循环
最后一点了,await必须在async函数的上下文中的。
// 正常 for 循环
async function forDemo() {
let arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i ++) {
await arr[i];
}
}
forDemo();//正常输出
// 因为想要炫技把 for循环写成下面这样
async function forBugDemo() {
let arr = [1, 2, 3, 4, 5];
arr.forEach(item => {
await item;
});
}
forBugDemo();// Uncaught SyntaxError: Unexpected identifier