Js開發_Vue 回調&異步常用總結


① 第一步: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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM