① 第一步:callback
1. 方法回调
<template>
<div class="hello">
<button type="button" @click="setCallBack()"> testCallback </button>
</div>
</template>
<script>
export default {
name: 'callback',
data () {
return {
result: 0
}
},
methods: {
setCallBack() {
this.init((res) => {
console.log(res)
})
},
init(callback) {
setTimeout(() => {
if(Math.random() <= 0.6) {
callback(1)
} else {
callback(2)
}
}, 100)
}
}
}
</script>
2:回调地狱
<template>
<div class="hello">
<button type="button" @click="startCallback()"> test </button>
</div>
</template>
<script>
export default {
name: 'callback',
data () {
return {
result: 0
}
},
methods: {
startCallback(){
setTimeout(()=>{
console.log('callback 0.5秒',new Date());
setTimeout(()=>{
console.log('callback 0.4秒',new Date());
setTimeout(()=>{
console.log('callback 0.3秒',new Date());
setTimeout(()=>{
console.log('callback 0.2秒',new Date());
setTimeout(()=>{
console.log('callback 0.1秒',new Date());
}, 100);
}, 200);
}, 300);
}, 400);
}, 500);
}
}
}
</script>
3. 回调地狱的改善
<template>
<div class="hello">
<button type="button" @click="startCallback()"> test </button>
</div>
</template>
<script>
export default {
name: 'callback',
data () {
return {
result: 0
}
},
methods: {
call1(next){
setTimeout(()=>{
console.log('callback 0.5秒',new Date());
next();
},500);
},
call2(next){
setTimeout(()=>{
console.log('callback 0.4秒',new Date());
next();
},400);
},
call3(next){
setTimeout(()=>{
console.log('callback 0.3秒',new Date());
next();
},300);
},
call4(next){
setTimeout(()=>{
console.log('callback 0.2秒',new Date());
next();
},200);
},
call5(){
setTimeout(()=>{
console.log('callback 0.1秒',new Date());
},100);
},
startCallback(){
this.call1(()=>{
this.call2(()=>{
this.call3(()=>{
this.call4(()=>{
this.call5();
});
});
});
});
}
}
}
</script>
② 第二步 : Promise
Promise他将提供一种更加优雅的方法,让我们写回调函数。
Promise是一个构造函数,自己身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样很眼熟的方法。
这么说用Promise new出来的对象肯定就有then、catch方法

Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise对象有以下两个特点:
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败)。
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
简单来说,Promise 就是用同步的方式写异步的代码,用来解决回调问题
<template>
<div class="hello">
<button type="button" @click="startCallback()"> test </button>
</div>
</template>
<script>
export default {
name: 'callback',
data () {
return {
result: 0
}
},
methods: {
call1(){
var p=new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('callback 0.5秒',new Date());
resolve();
},500);
});
return p;
},
call2(){
var p=new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('callback 0.4秒',new Date());
resolve();
},400);
});
return p;
},
call3(){
var p=new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('callback 0.3秒',new Date());
resolve();
},300);
});
return p;
},
call4(){
var p=new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('callback 0.2秒',new Date());
resolve();
},200);
});
return p;
},
call5(){
var p=new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('callback 0.1秒',new Date());
resolve();
},100);
});
return p;
},
startCallback() {
var self = this
this.call1()
.then(function(data){
return self.call2();
})
.then(function(data){
return self.call3();
})
.then(function(data){
return self.call4();
})
.then(function(data){
return self.call5();
})
}
}
}
</script>
第三步: Async/await/Promise
Async/await的主要益处是可以避免回调地狱(callback hell且以最接近同步代码的方式编写异步代码。
1.【方法中等待异步】
简单理解:async 是让方法变成异步 await是等待异步方法执行完毕。
<template>
<div class="hello">
<button type="button" @click="setPromise()"> test </button>
</div>
</template>
<script>
export default { name: 'HelloWorld', data () { return { result: 0 } }, methods: { setPromise() { var sleep = function (time) { return new Promise(function (resolve, reject) { setTimeout(function () { resolve('ok'); // reject('error'); }, time); }) }; var start = async function (self) { try { console.log('start async'); self.result = await sleep(3000); // 这里得到了一个返回错误 console.log('async后:'+ self.result); // 收到 ‘ok’ } catch (err) { console.log(err); // 这里捕捉到错误 `error` } }; start(this) console.log('async ago '+ this.result); // 收到 ‘ok’ } } } </script>
2. 【复数异步方法】
复数异步方法顺序执行
<template>
<div class="hello">
<button type="button" @click="setPromise()"> test </button>
</div>
</template>
<script>
export default { name: 'HelloWorld', data () { return { result: 0 } }, methods: { setPromise() { let initIndex = function(self) { Promise.resolve().then(function(){ console.log('step 1: start') return self.init() }).then(function(res) { console.log('step 2: ' + res) return self.getToken() }).then(function(token) { console.log('step 3: ' + token) return self.getServerData(1) }).then(function(data) { console.log('step 4: ' + data) return self.getServerData(2) }).then(function(data) { console.log('step 5: ' + data) console.log('finish') }) } initIndex(this) }, init() { return new Promise((resolve, reject) => { resolve('return true') }) }, getToken() { return new Promise((resolve, reject) => { resolve('return token') }) }, getServerData(data) { return new Promise((resolve, reject) => { resolve('return getServerData' + data) }) } } } </script>
3. 【复数异步方法】
复数方法优先执行
<template>
<div class="hello">
<button type="button" @click="setPromise()"> test </button>
</div>
</template>
<script>
export default { name: 'HelloWorld', data () { return { result: 0 } }, methods: { setPromise() { let $init = this.init() let $getToken = this.getToken() let $getServerData1 = this.getServerData(1) let $getServerData2 = this.getServerData(2) Promise.all([$init, $getToken, $getServerData1, $getServerData2]).then((values) => { console.log(values) console.log('finish') }); }, init() { return new Promise((resolve, reject) => { resolve('return true') }) }, getToken() { return new Promise((resolve, reject) => { resolve('return token') }) }, getServerData(data) { return new Promise((resolve, reject) => { resolve('return getServerData' + data) }) } } } </script>
4.【循环中等待异步】
<template>
<div class="hello">
<button type="button" @click="setAgvList()"> test </button>
<ul v-for="item in items">
<li>{{item.count}}:{{item.name}}</li>
</ul>
</div>
</template>
<script>
export default { name: 'HelloWorld', data () { return { items: [] } }, methods :{ setAgvList() { const commonAsync = async() => { for (var count = 0; count < 5; count++) { var name = await this.getRobotByIndex(count) var status = { count: count, name: name } this.items.push(status) } console.log(this.items) } commonAsync() }, async getRobotByIndex (agvIndex) { return "hello world!" + agvIndex } } } </script>
