成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Javascript 從異步函數(shù)到 Promise 到 Async/Await

yy736044583 / 620人閱讀

摘要:實(shí)例執(zhí)行以后,可以用方法分別指定狀態(tài)和狀態(tài)的回調(diào)函數(shù)。所以在使用處其中,函數(shù)接受回調(diào)函數(shù),作為對(duì)象的狀態(tài)變?yōu)闀r(shí)調(diào)用而回調(diào)函數(shù)作為對(duì)象的狀態(tài)變?yōu)闀r(shí)調(diào)用。

我最近正在看的一本書《聊聊架構(gòu)》,在進(jìn)入今天的主題之前,我想和大家分享這本書里的一個(gè)概念“生命周期”。

大致是這么說(shuō)的:

人類的生命很短,百年也只有短短的三萬(wàn)六千天。大部分人都不愿意接受一切都將消逝的事實(shí),總想活得更久,占有更多,享受更多。在人們短短的一生中,如何延長(zhǎng)自身的生命呢?一個(gè)辦法就是盡可能做出更多的成就,能夠讓更多的人生活得更好。在同樣的時(shí)間內(nèi)創(chuàng)造出更多的產(chǎn)出,相當(dāng)于把自己的生命延長(zhǎng)了。

其中有效的做法就是將每次活動(dòng)進(jìn)行拆分,自己執(zhí)行核心的【生命周期】,將【非核心生命周期】交給其它主體進(jìn)行。

比如,用戶購(gòu)物這一場(chǎng)景,從用戶進(jìn)入到商店,進(jìn)行瀏覽、詢問、購(gòu)買等活動(dòng),到離開商店,都是按時(shí)間順序一步一步在執(zhí)行的。對(duì)于我們來(lái)說(shuō),這其中的每一步都需要時(shí)間,對(duì)于現(xiàn)代人來(lái)說(shuō),太奢侈了。如果這時(shí)候,我們把這個(gè)購(gòu)物行為進(jìn)行拆分,把選購(gòu)交由別人執(zhí)行,由別人代替用戶上街選擇和過(guò)濾,或者通過(guò)網(wǎng)上推薦等來(lái)完成選購(gòu),用戶只需要最后確定物品的挑選即可。用戶的目的是買到自己需要的東西,而不是選購(gòu)本身。這樣就可以大大節(jié)省用戶的時(shí)間,將更多的精力放到其他核心事情上。

再比如,現(xiàn)在吃飯,需要自己到菜市場(chǎng)買菜、回來(lái)煮飯煮菜,吃完飯后,還需要自己洗碗等。有時(shí)候完全可以叫外賣的,肚子餓了,點(diǎn)點(diǎn)【餓了嗎】,接著就可以繼續(xù)做自己的事情了,坐等外賣送到。將【煮飯】這一耗時(shí)的事情交給別人來(lái)做。

在編程語(yǔ)言中,這就是同步與異步的區(qū)別。異步的作用就是將耗時(shí)的事情交給【別人】來(lái)做,自己繼續(xù)進(jìn)行;當(dāng)【別人】做完事情后,執(zhí)行回調(diào)函數(shù),帶回結(jié)果,交回自己執(zhí)行。

回調(diào)函數(shù)

雖然 Javascipt 語(yǔ)言是“單線程”執(zhí)行環(huán)境,但在執(zhí)行模式下,分成同步和異步兩種模式,其中我們更多的使用回調(diào)函數(shù)的方式來(lái)進(jìn)行異步操作,如:

blogs.search = (words, res) => {
    const titleQuery = new AV.Query(Blog)
    titleQuery.contains("title", words);

    const descQuery = new AV.Query(Blog)
    descQuery.contains("desc", words);

    const tagsQuery = new AV.Query(Blog)
    tagsQuery.contains("tags", words);

    const wordsQuery = AV.Query.or(titleQuery, descQuery, tagsQuery);

    wordsQuery.descending("createdAt");
    wordsQuery.limit(5);
    wordsQuery.find().then(function (results) {
        res(results);
    }, function (error) {
        res([]);
    });
}

這函數(shù)的作用就是通過(guò)關(guān)鍵詞words搜索,獲取滿足條件的公眾號(hào)文章,如果找不到就返回空數(shù)組。其中這里的res就是一個(gè)回調(diào)函數(shù)。在使用處:

server.route({
        method: "POST",
        path: "/searchblog",
        handler: function (request, reply) {
            const words = request.payload.words;
            ModelBlog.search(words, results => {
                let data = [];
                results.forEach(function(v) {
                    let wrap = {};

                    wrap.title = v.get("title");
                    wrap.description = v.get("desc");
                    wrap.picurl = v.get("picurl");
                    wrap.url = v.get("url");

                    data.push(wrap);
                });
                reply(data);
            });
        },
        config: {
            validate: {
                payload: {
                    words: Joi.string().required()
                }
            }
        }
    });

同樣的,在handler函數(shù)中的reply也是一個(gè)回調(diào)函數(shù),先通過(guò)ModelBlog.search函數(shù)內(nèi)嵌回調(diào)函數(shù)獲取數(shù)據(jù)庫(kù)中的文章數(shù)組,然后再對(duì)回調(diào)結(jié)果進(jìn)行處理,返回給回調(diào)函數(shù)reply,最后返回給前端使用。

通過(guò)一個(gè)簡(jiǎn)單的例子——“回調(diào)函數(shù),內(nèi)嵌回調(diào)函數(shù)”來(lái)說(shuō)明回調(diào)函數(shù)是可以無(wú)窮盡的內(nèi)嵌,結(jié)果就是各個(gè)部分之間高度耦合,流程混在一起,每個(gè)任務(wù)只能指定一個(gè)回調(diào)函數(shù)。最終造成的結(jié)果就會(huì)嵌入回調(diào)地獄,很可能就像這樣了——結(jié)尾是無(wú)止境的});

圖片來(lái)自于:
https://tutorialzine.com/media/2017/07/callback-hell.jpg

Promise 來(lái)源

所謂 Promise, 就是一個(gè)對(duì)象,用來(lái)傳遞異步操作的消息。它代表了某個(gè)未來(lái)才會(huì)知道結(jié)果的事件 (通常是一個(gè)異步操作),并且這個(gè)事件提供統(tǒng)一的 API,可供進(jìn)一步處理。

————來(lái)自《ES 6標(biāo)準(zhǔn)入門 (第二版)》

基于回調(diào)函數(shù)的異步處理如果統(tǒng)一參數(shù)使用規(guī)則的話,寫法也會(huì)很明了。但是,這也僅是編碼規(guī)范而已,即使采用不同的寫法也不會(huì)出錯(cuò)。

而 Promise 則是把類似的異步處理對(duì)象和處理規(guī)則進(jìn)行規(guī)范化,并按照采用統(tǒng)一的接口來(lái)編寫,而采用規(guī)定方法之外的寫法都會(huì)出錯(cuò)。

除了 Promise 對(duì)象規(guī)定的方法 (這里的 then 或 catch )以外的方法都是不可以使用的,而不會(huì)像回調(diào)函數(shù)方式那樣可以自己自由的定義回調(diào)函數(shù)的參數(shù),而必須嚴(yán)格遵守固定、統(tǒng)一的編碼方式來(lái)編寫代碼。

這樣,基于 Promise 的統(tǒng)一接口的做法,就可以形成基于接口的各種各樣的異步處理模式。所以,Promise 的功能是可以將復(fù)雜的異步處理輕松的進(jìn)行模式化,這也可以說(shuō)是使用 Promise 的理由之一。

Promise 在規(guī)范上規(guī)定 Promise 只能使用異步調(diào)用方式。
如果將上面的 demo 重新用 Promise 來(lái)寫呢:

blogs.promise_search = (words) => {
    const promise = new Promise(function (resolve, reject) {
        const titleQuery = new AV.Query(Blog)
        titleQuery.contains("title", words);

        const descQuery = new AV.Query(Blog)
        descQuery.contains("desc", words);

        const tagsQuery = new AV.Query(Blog)
        tagsQuery.contains("tags", words);

        const wordsQuery = AV.Query.or(titleQuery, descQuery, tagsQuery);

        wordsQuery.descending("createdAt");
        wordsQuery.limit(5);
        wordsQuery.find().then(function (results) {
            resolve(results);
        }, function (error) {
            reject(error);
        });
    });

    return promise;
}

Promise 構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù),該函數(shù)的兩個(gè)參數(shù)分別是 resolve 和 reject。它們是兩個(gè)函數(shù),由 Javascript 引擎提供,不用自己傳入。

其中,resolve 函數(shù)的作用是,將 Promise 對(duì)象的狀態(tài)從“未完成”變成“成功” (即從 Pending 變?yōu)?Resolved),在異步操作成功時(shí)調(diào)用,并將異步操作的結(jié)果作為參數(shù)傳遞出去;

reject 函數(shù)的作用是,將 Promise 對(duì)象的狀態(tài)從“未完成”變?yōu)椤笆 ?(即從 Pending 變?yōu)?Rejected),在異步操作失敗時(shí)調(diào)用,并將異步操作報(bào)出的錯(cuò)誤作為參數(shù)傳遞出去。

Promise 實(shí)例執(zhí)行以后,可以用then方法分別指定Resolved狀態(tài)和Rejected狀態(tài)的回調(diào)函數(shù)。所以在使用處:

const words = request.payload.words;
ModelBlog.promise_search(words).then(function (results) {
    let data = [];
    results.forEach(function(v) {
        let wrap = {};

        wrap.title = v.get("title");
        wrap.description = v.get("desc");
        wrap.picurl = v.get("picurl");
        wrap.url = v.get("url");

        data.push(wrap);
    });
    reply(data);
}).catch(function (error) {
    reply([]);
});

其中,then函數(shù)接受回調(diào)函數(shù),作為 Promise 對(duì)象的狀態(tài)變?yōu)?Resolved 時(shí)調(diào)用;而 catch 回調(diào)函數(shù)作為 Promise 對(duì)象的狀態(tài)變?yōu)?Rejected 時(shí)調(diào)用。和【異步函數(shù)】相比,簡(jiǎn)單明了很多了,至少不用再傳遞回調(diào)函數(shù)到 ModelBlog 中,可以做到代碼的分離,ModelBlog 的作用只是為了拿到數(shù)據(jù),返回 Promise 對(duì)象,具體外界怎么使用,那是別人的事情了;同樣在使用方,可以直接調(diào)用 Promise 對(duì)象,通過(guò) then 方法處理回調(diào)數(shù)據(jù)和錯(cuò)誤信息,代碼也就更容易理解了。

但寫代碼總不能到處都是 Promise 對(duì)象,既然 Promise 能解決異步調(diào)用地獄的問題,但還有沒有更好的辦法將 Promise 異步方法寫的和同步寫法那樣,畢竟很多人已經(jīng)習(xí)慣面向過(guò)程的編寫方式了?

Async/Await

Async/Await是一個(gè)很久就令人期待的 JavaScript 功能,它讓使用異步函數(shù)更加愉快和容易理解。它是基于 Promise 的并且和現(xiàn)存的所有基于 Promise 的 API 相兼容。

從 async 和 await 這兩個(gè)名字來(lái)的這兩個(gè)關(guān)鍵字將會(huì)幫助我們整理我們的異步代碼。

async function getBlogsAsync(words) {
    const titleQuery = new AV.Query(Blog)
    titleQuery.contains("title", words);

    const descQuery = new AV.Query(Blog)
    descQuery.contains("desc", words);

    const tagsQuery = new AV.Query(Blog)
    tagsQuery.contains("tags", words);

    const wordsQuery = AV.Query.or(titleQuery, descQuery, tagsQuery);

    wordsQuery.descending("createdAt");
    wordsQuery.limit(5);
    let results = await wordsQuery.find();
    return results;
}

這下連new Promise(...)都省了,直接寫核心業(yè)務(wù)代碼。很明顯 Async/Await 版本的代碼更短并且可讀性更強(qiáng)。除了使用的語(yǔ)法,兩個(gè)函數(shù)完全相同——他們都返回 Promise 并且都從數(shù)據(jù)庫(kù)得到 Blogs 數(shù)據(jù)返回。在使用時(shí),還是和之前一樣,直接調(diào)用getBlogsAsync方法:

getBlogsAsync(words).then(function (results) {
    let data = [];
    results.forEach(function(v) {
        let wrap = {};

        wrap.title = v.get("title");
        wrap.description = v.get("desc");
        wrap.picurl = v.get("picurl");
        wrap.url = v.get("url");

        data.push(wrap);
    });
    reply(data);
}).catch(function (error) {
    reply([]);
});
總結(jié)

隨著 Async/Await ,JavaScript語(yǔ)言在代碼可讀性和易用性上向前邁進(jìn)了一大步。而且寫異步代碼,就跟常規(guī)的寫面向過(guò)程的同步代碼一樣,簡(jiǎn)單直接明了。

最后分享幾個(gè)相關(guān)資料,值得一看,還有更多深入的內(nèi)容需要繼續(xù)挖掘:

Javascript異步編程的4種方法。http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html

《ES 6標(biāo)準(zhǔn)入門 (第二版)》,作者:阮一峰

JavaScript Async/Await Explained in 10 Minutes. https://tutorialzine.com/2017/07/javascript-async-await-explained

八段代碼徹底掌握 Promise. https://juejin.im/post/597724c26fb9a06bb75260e8

JavaScript Promise迷你書(中文版) http://liubin.org/promises-book/#promises-overview

理解 async/await. https://juejin.im/post/596e142d5188254b532ce2da

聽說(shuō)最美的人和最帥的人,都會(huì)給作者打賞,以資鼓勵(lì)

coding01 期待您關(guān)注

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/84604.html

相關(guān)文章

  • 如何正確合理使用 JavaScript async/await !

    摘要:想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳博客一年百來(lái)篇優(yōu)質(zhì)文章等著你引入的在的異步編程中是一個(gè)極好的改進(jìn)??赡軙?huì)產(chǎn)生誤導(dǎo)一些文章將與進(jìn)行了比較,并聲稱它是下一代異步編程風(fēng)格,對(duì)此作者深表異議。結(jié)論引入的關(guān)鍵字無(wú)疑是對(duì)異步編程的改進(jìn)。 showImg(https://segmentfault.com/img/bVbjFP0?w=800&h=450); 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來(lái)篇...

    trigkit4 評(píng)論0 收藏0
  • JavaScript是如何工作的:事件循環(huán)和異步編程的崛起+ 5種使用 async/await

    摘要:事件循環(huán)從回調(diào)隊(duì)列中獲取并將其推入調(diào)用堆棧。執(zhí)行從調(diào)用堆棧中移除從調(diào)用堆棧中移除快速回顧值得注意的是,指定了事件循環(huán)應(yīng)該如何工作,這意味著在技術(shù)上它屬于引擎的職責(zé)范圍,不再僅僅扮演宿主環(huán)境的角色。 此篇是 JavaScript是如何工作的第四篇,其它三篇可以看這里: JavaScript是如何工作的:引擎,運(yùn)行時(shí)和調(diào)用堆棧的概述! JavaScript是如何工作的:深入V8引擎&編寫...

    Honwhy 評(píng)論0 收藏0
  • JavaScript工作原理(四):事件循環(huán),異步編程的興起以及5招async/await實(shí)踐

    摘要:事件循環(huán)從回調(diào)隊(duì)列中獲取并將其推送到調(diào)用堆棧。如何工作請(qǐng)注意,不會(huì)自動(dòng)將您的回調(diào)函數(shù)放到事件循環(huán)隊(duì)列中。它設(shè)置了一個(gè)計(jì)時(shí)器,當(dāng)計(jì)時(shí)器到期時(shí),環(huán)境將您的回調(diào)函數(shù)放入事件循環(huán)中,以便將來(lái)的某個(gè)事件會(huì)將其選中并執(zhí)行它。 我們將通過(guò)回顧第一篇文章中單線程編程的缺點(diǎn),然后在討論如何克服它們來(lái)構(gòu)建令人驚嘆的JavaScript UI。在文章結(jié)尾處,我們將分享5個(gè)關(guān)于如何使用async / awai...

    piglei 評(píng)論0 收藏0
  • JavaScript 工作原理之四-事件循環(huán)及異步編程的出現(xiàn)和 5 種更好的 async/await

    摘要:函數(shù)會(huì)在之后的某個(gè)時(shí)刻觸發(fā)事件定時(shí)器。事件循環(huán)中的這樣一次遍歷被稱為一個(gè)。執(zhí)行完畢并出棧。當(dāng)定時(shí)器過(guò)期,宿主環(huán)境會(huì)把回調(diào)函數(shù)添加至事件循環(huán)隊(duì)列中,然后,在未來(lái)的某個(gè)取出并執(zhí)行該事件。 原文請(qǐng)查閱這里,略有改動(dòng)。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原理的第四章。 現(xiàn)在,我們將會(huì)通過(guò)回顧單線程環(huán)境下編程的弊端及如何克服這些困難以創(chuàng)建令人驚嘆...

    maochunguang 評(píng)論0 收藏0
  • 重構(gòu):PromiseAsync/Await

    摘要:一方面,這里替代的是異步代碼的編寫方式,并非完全拋棄大家心愛的,地球人都知道是基于的,不用太傷心另一方面,是基于回調(diào)函數(shù)實(shí)現(xiàn)的,那也沒有替代回調(diào)函數(shù)咯重構(gòu)代碼之后,我仍然用到了庫(kù)。 摘要: 夸張點(diǎn)說(shuō),技術(shù)的發(fā)展與歷史一樣,順之者昌,逆之者亡。JS開發(fā)者們,趕緊擁抱Async/Await吧! GitHub倉(cāng)庫(kù): Fundebug/promise-asyncawait 早在半年多之前,...

    zhangfaliang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<