成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

從js來聊聊異步編程

huashiou / 2762人閱讀

摘要:實(shí)例生成以后,可以用方法分別指定狀態(tài)和狀態(tài)的回調(diào)函數(shù)處理返回的結(jié)果。

文章的目的

揭開go的 gorouter,c#的 async/await等 使用同步的寫法寫異步代碼的神秘面紗 , 證明其本質(zhì)就是一個(gè)語法糖

為什么使用js來講異步編程

因?yàn)閖s可以通過編程語言自己的語法特性,實(shí)現(xiàn)async/await語法

js異步最底層寫法promise
const promise = new Promise(function(resolve, reject) {
  xxxxx.異步IO操作((res)=>{
      if(res成功){
          resolve(res)
      }else{
          reject(res)
      }
  })
});

promise出入的回調(diào)函數(shù)有一定的要求

resolve函數(shù)的作用是,將Promise對象的狀態(tài)從“未完成”變?yōu)椤俺晒Α保磸?pending 變?yōu)?resolved),在異步操作成功時(shí)調(diào)用,并將異步操作的結(jié)果,作為參數(shù)傳遞出去

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

Promise實(shí)例生成以后,可以用then方法分別指定resolved狀態(tài)和rejected狀態(tài)的回調(diào)函數(shù)(處理返回的結(jié)果)。
promise.then(function(value) {
  // success
}, function(error) {
  // failure
});
引申-注意: promise對象在js中非常特殊,比如下面的例子
const p1 = new Promise(function (resolve, reject) {
  setTimeout(() => reject(new Error("fail")), 3000)
})

const p2 = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(p1), 1000)
})
p2
  .then(result => console.log(result))
  .catch(error => console.log(error))
這個(gè)的結(jié)果是failt 因?yàn)?p2中resolve返回一個(gè)promise對象,這個(gè)操作將會導(dǎo)致p2的狀態(tài)升級成p1的狀態(tài)(標(biāo)準(zhǔn))
promise的then鏈?zhǔn)綄懛?/b>

promise then方法將會返回一個(gè)promise,所以js支持鏈?zhǔn)疆惒?/p>

var getJSON = function (url, callback) {
    var promise = new Promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        client.open("GET", url);
        client.onreadystatechange = handler;//readyState屬性的值由一個(gè)值變?yōu)榱硪粋€(gè)值時(shí),都會觸發(fā)readystatechange事件
        client.responseType = "json";
        client.setRequestHeader("Accept", "application/json");
        client.send();

        function handler() {
            if (this.readyState !== 4) {
                return;
            }
            if (this.status === 200) {
                callback(this.response);
                resolve(this.response);
            } else {
                reject(new Error(this.statusText))
            }
        };
    });
    return promise;
};
getJSON("./e2e-tests/get.json", function (resp) {
    console.log("get:" + resp.name);
}).then(function (json) {
    getJSON("./e2e-tests/get2.json", function (resp) {
        console.log("get2:" + resp.name);
    })
}).catch(function (error) {
    console.log("error1:" + error);
});
promise 異常捕獲
p.then((val) => console.log("fulfilled:", val))
  .catch((err) => console.log("rejected", err));

// 等同于
p.then((val) => console.log("fulfilled:", val))
  .then(null, (err) => console.log("rejected:", err));

這個(gè)異常捕獲和java相同,捕獲在eventLoop中產(chǎn)生的異常

注意一點(diǎn)這個(gè)異常和java的try catch是不同的,如果產(chǎn)生了異常將不會在主線程中顯示出來
promise的finally

這個(gè)和java的異常體系相同,finally 無關(guān)狀態(tài),最后都會執(zhí)行

Promise.resolve(2).finally(() => {})
更加方便的編寫異步使用Promise.resolve(xxx)
Promise.resolve("foo")
// 等價(jià)于
new Promise(resolve => resolve("foo"))
注意: promise異步化結(jié)果只能在回調(diào)函數(shù)中獲得,如果異步的操作太多,將會調(diào)至調(diào)用鏈路過長
如何解決js的promise異步編程的問題?

promise 寫法有什么問題? ---- 調(diào)用鏈路過長

比如: 使用promise 實(shí)現(xiàn) 異步ajax請求

var getJSON = function (url, callback) {
    var promise = new Promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        client.open("GET", url);
        client.onreadystatechange = handler;//readyState屬性的值由一個(gè)值變?yōu)榱硪粋€(gè)值時(shí),都會觸發(fā)readystatechange事件
        client.responseType = "json";
        client.setRequestHeader("Accept", "application/json");
        client.send();
        function handler() {
            if (this.readyState !== 4) {
                return;
            }
            if (this.status === 200) {
                callback(this.response);
                resolve(this.response);
            } else {
                reject(new Error(this.statusText))
            }
        };
    });
    return promise;
};
getJSON("./e2e-tests/get.json", function (resp) {
    console.log("get:" + resp.name);
}).then(function (json) {
    getJSON("./e2e-tests/get2.json", function (resp) {
        console.log("get2:" + resp.name);
    })
}).catch(function (error) {
    console.log("error1:" + error);
});

調(diào)用鏈太長,不停的promise調(diào)用

js如何解決回調(diào)地獄---同步方法寫異步 解決方法 使用js的協(xié)程 --Generator
generator:js的特殊語法,使用yield 關(guān)鍵字將函數(shù)分塊了,然后可以使用遍歷器手動控制執(zhí)行

例子:

function * gen(){
    let a= 123;
    let b = yield a;
    let c = yield a+b;
    return a+b+c;
}

let start = gen();

console.log(start.next());
console.log(start.next(2));
console.log(start.next(3));
本質(zhì)上是函數(shù)分片

js在每次yield的時(shí)候都會獲得當(dāng)前位置的表達(dá)式,然后再手動的嵌入就可以實(shí)現(xiàn)分片控制的效果了

怎么用generator實(shí)現(xiàn)異步化呢 -- yield配合promise實(shí)現(xiàn)異步

看一下這個(gè)方法

function* asyncFn(value) {
    let a = yield promiseOne(value);
    let b = yield promiseTwo(a);
    return a + b;
}

想讓他能異步執(zhí)行,只要能讓前一個(gè)promise的結(jié)果是下一個(gè)promise的輸入就可以了

這里有兩種寫法

寫法一

遞歸方程: f(最終結(jié)果) = f(到目前的結(jié)果)+f(接下來執(zhí)行的結(jié)果)

function promiseOne(xxx) {
    return new Promise((res, rej) => {
        res(xxx + 1);
    })
}
function promiseTwo(xxx) {
    return new Promise((res, rej) => {
        res(xxx + 1);
    })
}
function* asyncFn(value) {
    let a = yield promiseOne(value);
    let b = yield promiseTwo(a);
    return a + b;
}
function runAsync(fn,value) {
    let item = fn.next(value);
    return new Promise((res, rej) => {
        if (!item.done) {
            if (item.value instanceof Promise) {
                item.value.then((re)=>{
                    runAsync(fn,re).then(res);
                })
            } else {
                runAsync(fn,fn.valueOf()).then(res);
            }
        } else {
            res(item.value);//這個(gè)res方法其實(shí)是所有人的res方法
        }
    })
}
runAsync(asyncFn(12)).then(res=>{
    console.log(res);
});
co 工具包的寫法
function run (gen) {
  gen = gen()
  return next(gen.next())
  function next ({done, value}) {
    return new Promise(resolve => {
     if (done) { // finish
       resolve(value)
     } else { // not yet
       value.then(data => {
         next(gen.next(data)).then(resolve)
       })
     }
   })
  }
}
function getRandom () {
  return new Promise(resolve => {
    setTimeout(_ => resolve(Math.random() * 10 | 0), 1000)
  })
}
function * main () {
  let num1 = yield getRandom()
  let num2 = yield getRandom()
 
  return num1 + num2
}
run(main).then(data => {
  console.log(`got data: ${data}`);
})
寫法二

遞歸方程 f(最終結(jié)果) = f(之前所有的結(jié)果)+f(最后一步的結(jié)果)

//同步方式寫異步
function asyncRun(resf, fn, value) {
    let a = fn(value);
    go(value);
    function go(value) {
        let next = a.next(value);
        if (!next.done) {
            if (next.value instanceof Promise) {
                next.value.then((res) => {
                    go(res);
                });
            } else {
                return go(next.value);
            }
        } else {
            resf(next.value);
        }
    }
}
function* asyncFn(value) {
    let a = yield promiseOne(value);
    let b = yield promiseTwo(a);
    return a + b;
}
function show(item) {
    console.log(item)
}
asyncRun(show, asyncFn, 12);
function promiseOne(xxx) {
    return new Promise((res, rej) => {
        res(xxx + 1);
    })
}
function promiseTwo(xxx) {
    return new Promise((res, rej) => {
        res(xxx + 1);
    })
}
更簡單的方法 async/await

上面復(fù)雜的代碼如果變成async/await要怎么做呢

很簡單

// function* asyncFn(value) {
//     let a = yield promiseOne(value);
//     let b = yield promiseTwo(a);
//     return a + b;
// }
function promiseOne(xxx) {
    return new Promise((res, rej) => {
        res(xxx + 1);
    })
}
function promiseTwo(xxx) {
    return new Promise((res, rej) => {
        res(xxx + 1);
    })
}
async function asyncFn(value) {
    let a = await promiseOne(value);
    let b = await promiseTwo(a);
    return a + b;
}
asyncFn(12).then((res)=>{
    console.log(res)
});

通過上面的例子,我們可以發(fā)現(xiàn)其實(shí)async/await本質(zhì)上其實(shí)是 generator的一個(gè)語法糖

await就是yield , async 的作用就是將函數(shù)編程語法糖

如果背的話很簡答兩條規(guī)則:

await后面必須是promise函數(shù)

async 標(biāo)記過得函數(shù)執(zhí)行后返回的promise

通過這種方法就可以簡單的實(shí)現(xiàn)異步了

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/104296.html

相關(guān)文章

  • 聊聊 2018 年后端技術(shù)趨勢

    摘要:現(xiàn)在在后端業(yè)務(wù)開發(fā)編程方面,技術(shù)力量強(qiáng)的團(tuán)隊(duì)已經(jīng)開始將技術(shù)棧從同步模式切換為異步了。使用這些技術(shù)方案是無法兼容已有程序的。影響了異步回調(diào)技術(shù)棧的普及。將會成為未來后端開發(fā)領(lǐng)域的主流技術(shù)方案。 今天太忙,少寫一點(diǎn),后面再補(bǔ)充。 異步模式 Go 語言越來越熱門,很多大型互聯(lián)網(wǎng)公司后端正在轉(zhuǎn)向 GO 。Java 圈知名的服務(wù)化框架 Dubbo 也宣布轉(zhuǎn)型異步模式。這是一個(gè)大趨勢,異步模式已經(jīng)...

    Miyang 評論0 收藏0
  • 這次聊聊Promise對象

    摘要:異步模式編程有四種方法回調(diào)函數(shù)最基本的方法,把寫成的回調(diào)函數(shù)事件監(jiān)聽為綁定事件,當(dāng)發(fā)生某個(gè)事件,就執(zhí)行發(fā)布訂閱,以及本文要介紹的對象。它的思想是,每一個(gè)異步任務(wù)返回一個(gè)對象,該對象有一個(gè)方法,允許指定回調(diào)函數(shù)。 歡迎大家前往騰訊云+社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~ 本文由前端林子發(fā)表于云+社區(qū)專欄 Promise是CommonJS提出的一種規(guī)范,在ES6中已經(jīng)原生支持Promi...

    Eminjannn 評論0 收藏0
  • Javascript中的異步編程

    摘要:接下來,我們一起來看看中的異步編程,具體有哪幾種。實(shí)現(xiàn)異步編程的方法一回調(diào)函數(shù)上面不止一次提到了回調(diào)函數(shù)。它是異步編程中,最基本的方法。四對象接下來,我們聊聊與相關(guān)的異步編程方法,對象。 showImg(https://segmentfault.com/img/bVbneWy?w=1600&h=1200); 前言 最近,小伙伴S 問了我一段代碼: const funB = (value...

    wemall 評論0 收藏0
  • 2017-06-27 前端日報(bào)

    摘要:前端日報(bào)精選漫談函數(shù)式編程一十年蹤跡的博客前端每周清單的優(yōu)勢與劣勢有望超越在嵌入式及物聯(lián)網(wǎng)的應(yīng)用現(xiàn)狀進(jìn)階系列高階組件詳解一前端之路譯如何充分利用控制臺掘金程序猿升級攻略眾成翻譯中文譯如何充分利用控制臺掘金前端從強(qiáng)制開啟壓縮探 2017-06-27 前端日報(bào) 精選 漫談 JS 函數(shù)式編程(一) - 十年蹤跡的博客前端每周清單: Vue的優(yōu)勢與劣勢;Node.js有望超越Java;JS在嵌...

    Eidesen 評論0 收藏0
  • 只為那句承諾-大話Promise

    摘要:什么是是異步編程的一種解決方案,比傳統(tǒng)的解決方案回調(diào)函數(shù)和事件更合理和更強(qiáng)大。函數(shù)可以將狀態(tài)轉(zhuǎn)變?yōu)闋顟B(tài)。對象通過方法來添加回調(diào)函數(shù)。當(dāng)發(fā)生錯誤的時(shí)候可以通過方法,來定義回調(diào)函數(shù)。接受數(shù)組作為參數(shù)傳入,每個(gè)元素都是一個(gè)對象。 大家周末好,要說最近幾年什么語言大紅大紫,當(dāng)屬JavaScript了。話說雖然是10天就創(chuàng)造出的語言,但是人家能文能武。web前端自然不必多說了,各種框架你方登罷我...

    EastWoodYang 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<