async/await在CSS動畫控制中的簡單應用

最近在做一個H5動畫的小項目,由于項目周期充裕,前期主要是搭架構,也沒用其他多余的動畫庫。由于經驗不足,在搭架構的過程中也遇到挺多坑,比如webpack的配置問題、場景動畫類的封裝等等。這次就記錄下如何異步控制動畫的出現(xiàn)和消失。

回顧ES6的Promise和ES7的async/await

在ES6出來之前和不用其他動畫庫的情況下,很多人做簡單動畫基本都是用css3 animation + setTimeout + jQuery animate,但這樣卻面臨一個問題:沒錯,回調地獄和嵌套層次太深,代碼可讀性大打折扣。
但現(xiàn)在有了ES6、ES7和babel,我們可以大膽地用promise和async/await來做動畫的異步執(zhí)行。
async函數(shù)是generator的一個語法糖,目前能被babel編譯。它的優(yōu)點在于外部不需要手動調用next方法,也不需要鏈式調用then方法,可以說是優(yōu)于promise和generator。用法非常簡單,來看一個簡單例子:

const getUserData = url => (
    new Promise((resolve, reject) => {
       axios.get(url)
         .then(({ data }) => resolve(data))
         .catch(error => reject(error));
    })
);
const getUserDataByAsync = async () => {
    let _username;
    try{
      const { username } = await getUserData('https://github.com/username');
      _username = username;
      if(_username) {
        /* do something */
      }
    }catch(err){
      console.log(err);
    }
};
getUserDataByAsync();
  • 首先我們定義了一個getUserData函數(shù),返回一個promise對象實例,用于抓取github上的用戶信息。axios的get方法返回的也是一個promise對象,請求成功后會執(zhí)行第一層promise的resolve方法,并把請求到的數(shù)據傳出去。
  • 接下來定義一個名為getUserDataByAsync的async函數(shù)(也可以這么聲明: async function getUserDataByAsync(){}),用于處理請求成功后的操作。await關鍵字后調用getUserData,而在此之后的代碼(在try之內,await之后)則會被阻塞,待請求成功后才會繼續(xù)執(zhí)行。await getUserData()的返回值則是getUserData函數(shù)里resolve后傳入的data。這里我們用try-catch來捕獲請求失敗后的異常信息,catch打印出來的則是getUserData里請求失敗后reject傳入的error。
  • 最后再調用getUserDataByAsync函數(shù)就行了。
我們用同樣的方法封裝一個動畫延時器
  • 首先我們先封裝動畫方法,這里為了操作節(jié)點方便一點用了jQuery
const animate = several => {
     for (let effectName in several) {
       let effect = `${effectName}`,
           element_list = (several[effectName] instanceof Array) ? several[effectName] : [];

       element_list.forEach(element => {
         //為了防止display和animation沖突我們需要判斷元素是否被隱藏了
         if ($(element).is(':hidden')) {
           $(element).show();
           setTimeout(() => {
             $(element).addClass(`animated ${effect}`);
           }, 10);
         } else {
           $(element).addClass(`animated ${effect}`);
         }
       });
     }
};

需配合自己寫的css3 animation或引入animate.css庫。

  • 再封裝一個延時器
const delay = (timeout = 0) => (
    new Promise(resolve => {
      setTimeout(resolve, timeout);
    })
);
  • 之后就可以隨意控制動畫的出現(xiàn)和消失了
const pageAnimationStart = async () => {
    const _sceneWrap= $('#scene-wrap'),
          _title = _scene_wrap.find('.title'),
          _tree =  _scene_wrap.find('.tree'),
          _apples = _scene_wrap.find('.apple');

    animate({
      'scaleIn': [_sceneWrap]
    });

    await delay(1000);

    animate({
      'slideBounceInDown': [_tree]
    });

    await delay(1500);

    animate({
      'bounceIn': [_title, _apples]
    });
};
window.addEventListener('load', function(){
    pageAnimationStart();
}, false);

頁面加載完成后,場景開始,先是整個場景背景_sceneWrap放大進入,1秒后大樹_tree由上到下掉入,再過1.5秒后標題_title和蘋果_apples跳入。
大概就是這樣一個步奏,以異步執(zhí)行、同步寫法的方式,看起來特別舒服,清晰地展示了每一步該做什么,避免了的嵌套、回調和滿屏的then方法。

這就是async/await在動畫處理中的簡單方法。其他應用場景等我研究過后再記錄吧!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 異步編程對JavaScript語言太重要。Javascript語言的執(zhí)行環(huán)境是“單線程”的,如果沒有異步編程,根本...
    呼呼哥閱讀 7,405評論 5 22
  • javascript的運行機制是單線程處理,即只有上一個任務完成后,才會執(zhí)行下一個任務,這種機制也被稱為“同步”。...
    我是xy閱讀 3,992評論 1 6
  • 簡單介紹下這幾個的關系為方便起見 用以下代碼為例簡單介紹下這幾個東西的關系, async 在函數(shù)聲明前使用asyn...
    _我和你一樣閱讀 21,486評論 1 24
  • 相對于回調函數(shù)來說,Promise是一種相對優(yōu)雅的選擇。那么有沒有更好的方案呢?答案就是async/await。優(yōu)...
    松哥888閱讀 47,851評論 8 36
  • ·楔子求求你,求求你,留下來。不見了。 ·節(jié)一人生如夢,一樽還酹江月。我的人生就恍若一場夢,而夢中卻沒有你。即使我...
    勇猛的野鴨閱讀 429評論 0 1

友情鏈接更多精彩內容