前端基礎(chǔ)進階(十五):透徹掌握Promise的使用晶丘,讀這篇就夠了

Promise:高手必備

Promise的重要性我認為沒有必要多講黍氮,概括起來說就是四個字:必!須浅浮!得沫浆!掌!握脑题!件缸。

而且還要掌握透徹。這篇文章的開頭叔遂,主要分析一下他炊,為什么會有Promise出現(xiàn)。

在實際的使用中已艰,有非常多的應(yīng)用場景我們不能立即知道應(yīng)該如何繼續(xù)往下執(zhí)行痊末。最常見的一個場景就是ajax請求。通俗來說哩掺,由于網(wǎng)速的不同凿叠,可能你得到返回值的時間也是不同的,這個時候我們就需要等待嚼吞,結(jié)果出來了之后才知道怎么樣繼續(xù)下去盒件。

// 簡單的ajax原生實現(xiàn)
var url = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10';
var result;

var XHR = new XMLHttpRequest();
XHR.open('GET', url, true);
XHR.send();

XHR.onreadystatechange = function() {
    if (XHR.readyState == 4 && XHR.status == 200) {
        result = XHR.response;
        console.log(result);
    }
}

在ajax的原生實現(xiàn)中,利用了onreadystatechange事件舱禽,當該事件觸發(fā)并且符合一定條件時炒刁,才能拿到想要的數(shù)據(jù),之后才能開始處理數(shù)據(jù)誊稚。

這樣做看上去并沒有什么麻煩翔始,但如果這個時候罗心,我們還需要另外一個ajax請求,這個新ajax請求的其中一個參數(shù)城瞎,得從上一個ajax請求中獲取渤闷,這個時候我們就不得不等待上一個接口請求完成之后,再請求后一個接口脖镀。如下:

var url = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10';
var result;

var XHR = new XMLHttpRequest();
XHR.open('GET', url, true);
XHR.send();

XHR.onreadystatechange = function() {
    if (XHR.readyState == 4 && XHR.status == 200) {
        result = XHR.response;
        console.log(result);

        // 偽代碼
        var url2 = 'http:xxx.yyy.com/zzz?ddd=' + result.someParams;
        var XHR2 = new XMLHttpRequest();
        XHR2.open('GET', url, true);
        XHR2.send();
        XHR2.onreadystatechange = function() {
            ...
        }
    }
}

當出現(xiàn)第三個ajax(甚至更多)仍然依賴上一個請求時飒箭,我們的代碼就變成了一場災(zāi)難。這場災(zāi)難蜒灰,往往也被稱為回調(diào)地獄补憾。

因此我們需要一個叫做Promise的東西,來解決這個問題卷员。

當然,除了回調(diào)地獄之外腾务,還有一個非常重要的需求:為了代碼更加具有可讀性和可維護性毕骡,我們需要將數(shù)據(jù)請求與數(shù)據(jù)處理明確的區(qū)分開來。上面的寫法岩瘦,是完全沒有區(qū)分開未巫,當數(shù)據(jù)變得復(fù)雜時,也許我們自己都無法輕松維護自己的代碼了启昧。這也是模塊化過程中叙凡,必須要掌握的一個重要技能,請一定重視密末。

從前面幾篇文中的知識我們可以知道握爷,當我們想要確保某代碼在誰誰之后執(zhí)行時,我們可以利用函數(shù)調(diào)用棧严里,將我們想要執(zhí)行的代碼放入回調(diào)函數(shù)中新啼。

// 一個簡單的封裝
function want() {
    console.log('這是你想要執(zhí)行的代碼');
}

function fn(want) {
    console.log('這里表示執(zhí)行了一大堆各種代碼');

    // 其他代碼執(zhí)行完畢,最后執(zhí)行回調(diào)函數(shù)
    want && want();
}

fn(want);

利用回調(diào)函數(shù)封裝刹碾,是我們在初學(xué)JavaScript時常常會使用的技能燥撞。

確保我們想要的代碼壓后執(zhí)行,除了利用函數(shù)調(diào)用棧的執(zhí)行順序之外迷帜,我們還可以利用上一篇文章所述的隊列機制物舒。

function want() {
    console.log('這是你想要執(zhí)行的代碼');
}

function fn(want) {
    // 將想要執(zhí)行的代碼放入隊列中,根據(jù)事件循環(huán)的機制戏锹,我們就不用非得將它放到最后面了冠胯,由你自由選擇
    want && setTimeout(want, 0);
    console.log('這里表示執(zhí)行了一大堆各種代碼');
}

fn(want);

如果瀏覽器已經(jīng)支持了原生的Promise對象,那么我們就知道景用,瀏覽器的js引擎里已經(jīng)有了Promise隊列涵叮,這樣就可以利用Promise將任務(wù)放在它的隊列中去惭蹂。

function want() {
    console.log('這是你想要執(zhí)行的代碼');
}

function fn(want) {
    console.log('這里表示執(zhí)行了一大堆各種代碼');

    // 返回Promise對象
    return new Promise(function(resolve, reject) {
        if (typeof want == 'function') {
            resolve(want);
        } else {
            reject('TypeError: '+ want +'不是一個函數(shù)')
        }
    })
}

fn(want).then(function(want) {
    want();
})

fn('1234').catch(function(err) {
    console.log(err);
})

看上去變得更加復(fù)雜了「盍福可是代碼變得更加健壯盾碗,處理了錯誤輸入的情況。

為了更好的往下擴展Promise的應(yīng)用舀瓢,這里需要先跟大家介紹一下Promsie的基礎(chǔ)知識廷雅。

一、 Promise對象有三種狀態(tài)京髓,他們分別是:

  • pending: 等待中航缀,或者進行中,表示還沒有得到結(jié)果
  • resolved(Fulfilled): 已經(jīng)完成堰怨,表示得到了我們想要的結(jié)果芥玉,可以繼續(xù)往下執(zhí)行
  • rejected: 也表示得到結(jié)果,但是由于結(jié)果并非我們所愿备图,因此拒絕執(zhí)行

這三種狀態(tài)不受外界影響灿巧,而且狀態(tài)只能從pending改變?yōu)閞esolved或者rejected,并且不可逆揽涮。在Promise對象的構(gòu)造函數(shù)中抠藕,將一個函數(shù)作為第一個參數(shù)。而這個函數(shù)蒋困,就是用來處理Promise的狀態(tài)變化盾似。

new Promise(function(resolve, reject) {
    if(true) { resolve() };
    if(false) { reject() };
})

上面的resolve和reject都為一個函數(shù),他們的作用分別是將狀態(tài)修改為resolved和rejected雪标。

二零院、 Promise對象中的then方法,可以接收構(gòu)造函數(shù)中處理的狀態(tài)變化汰聋,并分別對應(yīng)執(zhí)行门粪。then方法有2個參數(shù),第一個函數(shù)接收resolved狀態(tài)的執(zhí)行烹困,第二個參數(shù)接收reject狀態(tài)的執(zhí)行玄妈。

function fn(num) {
    return new Promise(function(resolve, reject) {
        if (typeof num == 'number') {
            resolve();
        } else {
            reject();
        }
    }).then(function() {
        console.log('參數(shù)是一個number值');
    }, function() {
        console.log('參數(shù)不是一個number值');
    })
}

fn('hahha');
fn(1234);

then方法的執(zhí)行結(jié)果也會返回一個Promise對象。因此我們可以進行then的鏈式執(zhí)行髓梅,這也是解決回調(diào)地獄的主要方式拟蜻。

function fn(num) {
    return new Promise(function(resolve, reject) {
        if (typeof num == 'number') {
            resolve();
        } else {
            reject();
        }
    })
    .then(function() {
        console.log('參數(shù)是一個number值');
    })
    .then(null, function() {
        console.log('參數(shù)不是一個number值');
    })
}

fn('hahha');
fn(1234);

then(null, function() {}) 就等同于catch(function() {})

三、Promise中的數(shù)據(jù)傳遞

大家自行從下面的例子中領(lǐng)悟吧枯饿。

var fn = function(num) {
    return new Promise(function(resolve, reject) {
        if (typeof num == 'number') {
            resolve(num);
        } else {
            reject('TypeError');
        }
    })
}

fn(2).then(function(num) {
    console.log('first: ' + num);
    return num + 1;
})
.then(function(num) {
    console.log('second: ' + num);
    return num + 1;
})
.then(function(num) {
    console.log('third: ' + num);
    return num + 1;
});

// 輸出結(jié)果
first: 2
second: 3
third: 4

OK酝锅,了解了這些基礎(chǔ)知識之后,我們再回過頭奢方,利用Promise的知識搔扁,對最開始的ajax的例子進行一個簡單的封裝爸舒。看看會是什么樣子稿蹲。

var url = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10';

// 封裝一個get請求的方法
function getJSON(url) {
    return new Promise(function(resolve, reject) {
        var XHR = new XMLHttpRequest();
        XHR.open('GET', url, true);
        XHR.send();

        XHR.onreadystatechange = function() {
            if (XHR.readyState == 4) {
                if (XHR.status == 200) {
                    try {
                        var response = JSON.parse(XHR.responseText);
                        resolve(response);
                    } catch (e) {
                        reject(e);
                    }
                } else {
                    reject(new Error(XHR.statusText));
                }
            }
        }
    })
}

getJSON(url).then(resp => console.log(resp));

為了健壯性扭勉,處理了很多可能出現(xiàn)的異常,總之苛聘,就是正確的返回結(jié)果涂炎,就resolve一下,錯誤的返回結(jié)果设哗,就reject一下唱捣。并且利用上面的參數(shù)傳遞的方式,將正確結(jié)果或者錯誤信息通過他們的參數(shù)傳遞出來网梢。

現(xiàn)在所有的庫幾乎都將ajax請求利用Promise進行了封裝震缭,因此我們在使用jQuery等庫中的ajax請求時,都可以利用Promise來讓我們的代碼更加優(yōu)雅和簡單战虏。這也是Promise最常用的一個場景蛀序,因此我們一定要非常非常熟悉它,這樣才能在應(yīng)用的時候更加靈活活烙。

四、Promise.all

當有一個ajax請求遣鼓,它的參數(shù)需要另外2個甚至更多請求都有返回結(jié)果之后才能確定啸盏,那么這個時候,就需要用到Promise.all來幫助我們應(yīng)對這個場景骑祟。

Promise.all接收一個Promise對象組成的數(shù)組作為參數(shù)回懦,當這個數(shù)組所有的Promise對象狀態(tài)都變成resolved或者rejected的時候,它才會去調(diào)用then方法次企。

var url = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10';
var url1 = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-03-26/2017-06-10';

function renderAll() {
    return Promise.all([getJSON(url), getJSON(url1)]);
}

renderAll().then(function(value) {
    // 建議大家在瀏覽器中看看這里的value值
    console.log(value);
})

五怯晕、 Promise.race

與Promise.all相似的是,Promise.race都是以一個Promise對象組成的數(shù)組作為參數(shù)缸棵,不同的是舟茶,只要當數(shù)組中的其中一個Promsie狀態(tài)變成resolved或者rejected時,就可以調(diào)用.then方法了堵第。而傳遞給then方法的值也會有所不同吧凉,大家可以再瀏覽器中運行下面的例子與上面的例子進行對比。

function renderRace() {
    return Promise.race([getJSON(url), getJSON(url1)]);
}

renderRace().then(function(value) {
    console.log(value);
})

嗯踏志,我所知道的阀捅,關(guān)于Promise的基礎(chǔ)知識就這些了,如果還有別的针余,歡迎大家補充饲鄙。

那么接下來凄诞,我們要結(jié)合三個不同的應(yīng)用場景來讓大家感受一下Promise在模塊系統(tǒng)中如何使用。

這里選擇requirejs是因為學(xué)習(xí)成本最低忍级,能夠快速上手進行簡單的運用帆谍。接下來的這些例子,會涉及到很多其他的知識颤练,因此如果想要徹底掌握既忆,一定要動手實踐,自己試著完成一遍嗦玖。

我在github上創(chuàng)建了對應(yīng)的項目患雇,大家可以直接clone下來進行學(xué)習(xí)。這樣學(xué)習(xí)效果會更好宇挫。

項目地址: https://github.com/yangbo5207/promiseApps

往下閱讀例子之前苛吱,請一定要對requirejs有一個簡單的了解。

requirejs中文文檔 http://www.requirejs.cn/

代碼結(jié)構(gòu)

項目的代碼結(jié)果如上圖所示器瘪,所有的html文件都放在根目錄下翠储。

  • pages: html直接引入的js
  • libs: 常用的庫
  • components: 針對項目自定義的模塊

首先為了能夠讓require起作用,我們需要在html中引入require.js橡疼,寫法如下:

// index.js為入口文件
<script data-main="./pages/index.js" src="./libs/require.js"></script>

在入口的index.js中援所,我們可以對常用的模塊進行映射配置,這樣在引入時就可以少寫一些代碼欣除。

// 具體的配置項的含義住拭,請參閱require的中文文檔
requirejs.config({
    baseUrl: './',
    paths: {
        jquery: "./libs/jquery-3.2.0",
        API: './libs/API',
        request: './libs/request',
        calendar: './components/calendar',
        imageCenter: './components/imageCenter',
        dialog: './components/Dialog'
    }
})

配置之后,那么我們在其他模塊中历帚,引入配置過的模塊滔岳,就可以簡單的這樣寫:

var $ = require('jquery');

如果不進行配置,也可以這樣引入模塊:

require('./components/button');

我們可以使用define定義一個模塊:

// 其他方式請參閱文檔
define(function(require) {

})

使用return可以直接對外提供方法:

// 在其他模塊通過require引入時得到的值挽牢,就是這里返回的值
define(function(require) {
    return {
        a: 1
    }
})

OK谱煤,了解上面這些,應(yīng)付基礎(chǔ)的使用已經(jīng)沒有問題了禽拔。我們接下來重點總結(jié)第一個常用的應(yīng)用場景:ajax刘离。

關(guān)于ajax的簡單使用和簡單封裝,我們在上面都已經(jīng)講過了睹栖,這里就不再多說寥闪,直接使用jquery封裝好的方法即可。而我們需要處理的問題在于磨淌,如何有效的將ajax的數(shù)據(jù)請求和數(shù)據(jù)處理分別放在不同的模塊中進行管理疲憋,這樣做的主要目的在于降低后期維護成本,便于管理梁只。

來看看怎么樣簡單操作的缚柳。

首先埃脏,將所有的url放在一個模塊中統(tǒng)一處理。

// libs/API.js
define(function() {
    return {
        dayInfo: 'https://hq.tigerbrokers.com/fundamental/finance_calendar/get_day/2017-04-03',
        typeInfo: 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-03-26/2017-04-15'
    }
})

在實際開發(fā)中秋忙,url并不是直接通過字符串就能直接確認的彩掐,某些url還需要通過參數(shù)拼接等,這個時候需要我們靈活處理灰追。

第二步堵幽,將所有的數(shù)據(jù)請求這個動作放在同一個模塊中統(tǒng)一管理。

// libs/request.js
define(function(require) {
    var API = require('API');

    // 因為jQuery中的get方法也是通過Promise進行了封裝弹澎,最終返回的是一個Promise對象朴下,因此這樣我們就可以將數(shù)據(jù)請求與數(shù)據(jù)處理放在不同的模塊
    // 這樣我們就可以使用一個統(tǒng)一的模塊來管理所有的數(shù)據(jù)請求

    // 獲取當天的信息
    getDayInfo = function() {
        return $.get(API.dayInfo);
    }

    // 獲取type信息
    getTypeInfo = function() {
        return $.get(API.typeInfo);
    };

    return {
        getDayInfo: getDayInfo,
        getTypeInfo: getTypeInfo
    }
});

在這個模塊中,我們還可以對拿到的數(shù)據(jù)進行一些你需要的過濾處理苦蒿,確保最終返回給下一個模塊的數(shù)據(jù)是能夠直接使用的殴胧。

第三步:就是拿到數(shù)據(jù)并且處理數(shù)據(jù)了。

// components/calendar.js
define(function(require) {
    var request = require('request');

    // 拿到數(shù)據(jù)之后佩迟,需要處理的組件团滥,可以根據(jù)數(shù)據(jù)渲染出需求想要的樣式
    // 當然這里為了簡化,就僅僅只是輸出數(shù)據(jù)就行了报强,在實際中灸姊,拿到數(shù)據(jù)之后還要進行相應(yīng)的處理

    request.getTypeInfo()
        .then(function(resp) {

            // 拿到數(shù)據(jù),并執(zhí)行處理操作
            console.log(resp);
        })

    // 這樣秉溉,我們就把請求數(shù)據(jù)厨钻,與處理數(shù)據(jù)分離開來,維護起來就更加方便了坚嗜,代碼結(jié)構(gòu)也足夠清晰
})

這就是我所了解的處理ajax的比較好的一個方式,如果你有其他更好的方式也歡迎分享苍蔬。

第二個應(yīng)用場景就是圖片加載的問題。
在一些實際應(yīng)用中蝴蜓,常常會有一些圖片需要放置在某一個塊中碟绑,比如頭像,比如某些圖片列表茎匠「裰伲可是源圖片的尺寸可能很難保證長寬比例都是一致的,如果我們直接給圖片設(shè)定寬高诵冒,就有可能導(dǎo)致圖片變形凯肋。變形之后高大上的頁面就直接垮掉了。

因此為了解決這個問題汽馋,我們需要一個定制的image組件來解決這個問題侮东。我們期望圖片能夠根據(jù)自己的寬高比圈盔,合理的縮放,保證在這個塊中不變形的情況下盡可能的顯示更多的內(nèi)容悄雅。

假如有一堆圖片驱敲,如下:

<section class="img-wrap">
    <div class="img-center">
        ![](https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1491191204817&di=48ea9cde3319576ed6e0b6dc6c6b75b4&imgtype=0&src=http%3A%2F%2Fa.hiphotos.baidu.com%2Fzhidao%2Fpic%2Fitem%2F342ac65c103853438b3c5f8b9613b07ecb8088ad.jpg)
    </div>

    <div class="img-center">
        ![](https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1491191241712&di=9dbd9c614b82f0b02c92c6e60875983a&imgtype=0&src=http%3A%2F%2Fpic5.qiyipic.com%2Fcommon%2F20130524%2F7dc5679567cd4243a0a41e5bf626ad77.jpg%3Fsrc%3Dfocustat_4_20130527_7)
    </div>

    <div class="img-center">
        ![](https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1491191271233&di=0c9dd2677413beadcccd66b9d4598c6b&imgtype=0&src=http%3A%2F%2Fb.zol-img.com.cn%2Fdesk%2Fbizhi%2Fimage%2F4%2F960x600%2F1390442684896.jpg)
    </div>

    <div class="img-center">
        ![](https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1491191294538&di=6474f3b560f2c100e62f118dde7e8d6c&imgtype=0&src=http%3A%2F%2Ff.hiphotos.baidu.com%2Fzhidao%2Fpic%2Fitem%2Fc9fcc3cec3fdfc03dfdfafcad23f8794a4c22618.jpg)
    </div>
</section>

每一張圖片都有一個包裹的div,這些div的寬高宽闲,就是我們期望圖片能保持的寬高众眨。

當圖片寬度值過大時,我們期望圖片的高度為100%容诬,并且左右居中娩梨。
當圖片高度值過大時,我們期望圖片的寬度為100%放案,并且上下居中姚建。

根據(jù)這一點,我們來看看具體怎么實現(xiàn)吱殉。

首先是樣式的定義很重要掸冤。

.img-center {
    width: 200px;
    height: 150px;
    margin: 20px;
    overflow: hidden;
    position: relative;
}

.img-center img {
    display: block;
    position: absolute;
}

.img-center img.aspectFill-x {
    width: 100%;
    top: 50%;
    transform: translateY(-50%);
}

.img-center img.aspectFill-y {
    height: 100%;
    left: 50%;
    transform: translateX(-50%);
}

我分別定義了aspectFill-xaspectFill-y,通過判斷不同的寬高比友雳,來決定將他們中的其中一個加入到img標簽的class中去即可稿湿。

獲取圖片的原始寬高,需要等到圖片加載完畢之后才能獲取押赊。而當圖片已經(jīng)存在緩存時饺藤,則有一個compete屬性變成true。那么我們就可以根據(jù)這些基礎(chǔ)知識流礁,定義一個模塊來處理這件事情涕俗。

// components/imageCenter.js
define(function(require) {

    // 利用Promise封裝一個加載函數(shù),這里也是可以單獨放在一個功能模塊中進一步優(yōu)化
    var imageLoad = function(img) {
        return new Promise(function(resolve, reject) {
            if (img.complete) {
                resolve();
            } else {
                img.onload = function(event) {
                    resolve(event);
                }

                img.onerror = function(err) {
                    reject(err);
                }
            }
        })
    }

    var imageCenter = function(domList, mode) {

        domList.forEach(function(item) {
            var img = item.children[0];
            var itemW = item.offsetWidth;
            var itemH = item.offsetHeight;
            var itemR = itemW / itemH;

            imageLoad(img).then(function() {
                var imgW = img.naturalWidth;
                var imgH = img.naturalHeight;
                var imgR = imgW / imgH;

                var resultMode = null;

                switch (mode) {
                    // 這樣寫是因為期待未來可以擴展其他的展示方式
                    case 'aspectFill':
                        resultMode = imgR > 1 ? 'aspectFill-x' : 'aspectFill-y';
                        break;
                    case 'wspectFill':
                        resultMode = itemR > imgR ? 'aspectFill-x' : 'aspectFill-y'
                        break;
                    default:
                }

                $(img).addClass(resultMode);
            })
        })
    }

    return imageCenter;
})

那么在使用時神帅,直接引入這個模塊并調(diào)用imageCenter方法即可再姑。

// index.js
var imageCenter = require('imageCenter');
var imageWrapList = document.querySelectorAll('.img-center');
imageCenter(imageWrapList, 'wspectFill');
一堆尺寸亂七八糟的圖片就這樣被馴服了

第三個應(yīng)用場景,則是自定義彈窗的處理找御。

這種類型的彈窗隨處可見元镀,而且十分常用

因此自己專門定義一個常用的彈窗就變得非常有必要,這對于我們開發(fā)效率的提高非常有幫助霎桅。當然栖疑,我這里只是簡單的寫了一個簡陋的,僅供參考滔驶。

我們期望的是利用Promise遇革,當我們點擊確認時,狀態(tài)變成resolved,點擊取消時澳淑,狀態(tài)變成rejected比原。這樣也方便將彈窗生成與后續(xù)的操作處理區(qū)分開來。

先定義一個Dialog模塊杠巡。使用的是最簡單的方式定義量窘,應(yīng)該不會有什么理解上的困難。主要提供了show和hide2個方法氢拥,用于展示和隱藏蚌铜。

// components/Dialog.js
define(function(require) {

    // 利用閉包的特性,判斷是否已經(jīng)存在實例
    var instance;

    function Dialog(config) {

        this.title = config.title ? config.title : '這是標題';
        this.content = config.content ? config.content : '這是提示內(nèi)容';

        this.html = '<div class="dialog-dropback">' +
            '<div class="container">' +
                '<div class="head">'+ this.title +'</div>' +
                '<div class="content">'+ this.content +'</div>' +
                '<div class="footer">' +
                    '<button class="cancel">取消</button>' +
                    '<button class="confirm">確認</button>' +
                '</div>' +
            '</div>' +
        '</div>'
    }

    Dialog.prototype = {
        constructor: Dialog,
        show: function() {
            var _this = this;
            if (instance) {
                this.destory();
            }
            $(this.html).appendTo($(document.body));
            instance = this;

            return new Promise(function(resolve, reject) {
                $('.dialog-dropback .cancel').on('click', function(e) {
                    _this.hide();
                    reject(e);
                })

                $('.dialog-dropback .confirm').on('click', function(e) {
                    _this.hide();
                    resolve(e);
                })
            })
        },

        destory: function() {
            instance = null;
            $('.dialog-dropback .cancel').off('click');
            $('.dialog-dropback .confirm').off('click');
            $('.dialog-dropback').remove();
        },

        hide: function() {
            this.destory();
        }
    }

    return function(config) {
        return new Dialog(config);
    }
})

那么在另外一個模塊中需要使用它時:

define(function(require) {
    var Dialog = require('dialog');

    $('button.aspect').on('click', function() {
        Dialog({
            title: '友情提示',
            content: '外面空氣不太好嫩海,你確定你要出門逛逛嗎冬殃?'
        }).show().then(function() {
            console.log('你點擊了確認按鈕.');
        }).catch(function() {
            console.log('你點擊了取消按鈕.');
        })
    })
})

這三種場景就介紹完了,主要是需要大家通過源碼來慢慢理解和揣摩叁怪。真正掌握之后审葬,相信大家對于Promise在另外的場景中的使用也會變得得心應(yīng)手。

最后總結(jié)一下奕谭,這篇文章涣觉,涉及到的東西,有點多血柳。大概包括Promise基礎(chǔ)知識官册,ajax基礎(chǔ)知識,如何利用Promise封裝ajax难捌,如何使用require模塊系統(tǒng)膝宁,如何在模塊中使用Promise,并且對應(yīng)的三個應(yīng)用場景又各自有許多需要了解的知識根吁,因此對于基礎(chǔ)稍差的朋友來說员淫,理解透徹了肯定會有一個比較大的進步。當然也會花費你更多的時間击敌。

另外在我們的工作中還有一件非常重要的事情是需要我們持續(xù)去做的介返。那就是將常用的場景封裝成為可以共用的模塊,等到下次使用時愚争,就可以直接拿來使用而節(jié)省非常多的開發(fā)時間。比如我這里對于img的處理挤聘,對于彈窗的處理轰枝,都是可以擴展成為一個通用的模塊的。慢慢積累多了组去,你的開發(fā)效率就可以得到明顯的提高鞍陨,這些積累,也將會變成你的優(yōu)勢所在。

后續(xù)的文章我會分享如何利用react與es6模塊系統(tǒng)封裝的共用組件诚撵,大家也可以學(xué)習(xí)了之后缭裆,根據(jù)自己的需求,封裝最適合你自己的一套組件寿烟。

最后澈驼,最近問我怎么學(xué)習(xí)的人越來越多,我真的有點回答不過來了筛武,我想把我這些文章里的知識都掌握了缝其,應(yīng)付畢業(yè)之后的第一份工作應(yīng)該不是什么問題的吧?而且為了你們能夠掌握Promise的使用终娃,我還專門給讀者老爺們創(chuàng)建了一個項目视乐,列舉了整整三個實例注簿,還有源代碼供你們學(xué)習(xí),我學(xué)Promise的時候漠其,找好久都沒找到一個稍微接近實際應(yīng)用的案例,學(xué)了好久才知道怎么使用竿音,效率之低可想而知和屎。所以靜下心來慢慢學(xué)習(xí)吧,花點時間是值得的 ~ ~ 谍失。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末眶俩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子快鱼,更是在濱河造成了極大的恐慌颠印,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抹竹,死亡現(xiàn)場離奇詭異线罕,居然都是意外死亡,警方通過查閱死者的電腦和手機窃判,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門钞楼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人袄琳,你說我怎么就攤上這事询件。” “怎么了唆樊?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵宛琅,是天一觀的道長。 經(jīng)常有香客問我逗旁,道長嘿辟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮红伦,結(jié)果婚禮上英古,老公的妹妹穿的比我還像新娘。我一直安慰自己昙读,他們只是感情好召调,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著箕戳,像睡著了一般某残。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上陵吸,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天玻墅,我揣著相機與錄音,去河邊找鬼壮虫。 笑死澳厢,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的囚似。 我是一名探鬼主播剩拢,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼饶唤!你這毒婦竟也來了徐伐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤募狂,失蹤者是張志新(化名)和其女友劉穎办素,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祸穷,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡性穿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了雷滚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片需曾。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖祈远,靈堂內(nèi)的尸體忽然破棺而出呆万,到底是詐尸還是另有隱情,我是刑警寧澤车份,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布谋减,位于F島的核電站,受9級特大地震影響躬充,放射性物質(zhì)發(fā)生泄漏逃顶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一充甚、第九天 我趴在偏房一處隱蔽的房頂上張望以政。 院中可真熱鬧,春花似錦伴找、人聲如沸盈蛮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抖誉。三九已至,卻和暖如春衰倦,著一層夾襖步出監(jiān)牢的瞬間袒炉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工樊零, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留我磁,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓驻襟,卻偏偏與公主長得像夺艰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沉衣,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容