異步流程控制(Callback 烙博、Promise瑟蜈、Generator + co、async + await)

一. Callback (回調(diào)函數(shù))

1.定義:把函數(shù)當(dāng)作變量傳到另一個函數(shù)里渣窜,傳進去之后執(zhí)行甚至返回等待之后的執(zhí)行铺根。
2.一個簡單的例子

function add_callback(p1, p2 ,callback) {
var my_number = p1 + p2;
callback(my_number);
}
add_callback(5, 15, function(num){
console.log("call " + num);
});

3. error first

1.回調(diào)函數(shù)的第一個參數(shù)保留給一個錯誤error對象,如果有錯誤發(fā)生乔宿,錯誤將通過第一個參數(shù)err返回位迂。
2.回調(diào)函數(shù)的第二個參數(shù)為成功響應(yīng)的數(shù)據(jù)保留,如果沒有錯誤發(fā)生,err將被設(shè)置為null, 成功的數(shù)據(jù)將從第二個參數(shù)返回掂林。

4.callback hell

JavaScript 是由事件驅(qū)動的異步編程臣缀,一個異步的操作,我們在調(diào)用他的時候党饮,不會馬上得到結(jié)果肝陪,而是會繼續(xù)執(zhí)行后面的代碼。這樣刑顺,如果我們需要在查到結(jié)果之后才做某些事情的話氯窍,就需要把相關(guān)的代碼寫在回調(diào)里面,如果涉及到多個這樣的異步操作蹲堂,就勢必會陷入到回調(diào)地獄中去狼讨。eg:
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})

二. Promise(為了解決callback hell的問題)

1. Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強大柒竞。ES6將其寫進了語言標(biāo)準政供,統(tǒng)一了用法,原生提供了Promise對象朽基。
2. Promise A+規(guī)范:

Promise 規(guī)范有很多布隔,如 Promise/A,Promise/B稼虎,Promise/D 以及 Promise/A 的升級版 Promise/A+衅檀,最終 ES6 中采用了 Promise/A+ 規(guī)范。Promise/A+ 官網(wǎng):https://promisesaplus.com/

3.promise對象的特點

1.對象的狀態(tài)不受外界影響霎俩,promise對象代表一個異步操作哀军,有三種狀態(tài),pending(進行中)打却、fulfilled(已成功)杉适、rejected(已失敗)柳击。只有異步操作的結(jié)果猿推,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個狀態(tài)捌肴,這也是promise這個名字的由來“承諾”彤守;
2.一旦狀態(tài)改變就不會再變,任何時候都可以得到這個結(jié)果哭靖,promise對象的狀態(tài)改變具垫,只有兩種可能:從pending變?yōu)閒ulfilled,從pending變?yōu)閞ejected试幽。這時就稱為resolved(已定型)筝蚕。如果改變已經(jīng)發(fā)生了卦碾,你再對promise對象添加回調(diào)函數(shù),也會立即得到這個結(jié)果起宽,這與事件(event)完全不同洲胖,事件的特點是:如果你錯過了它,再去監(jiān)聽是得不到結(jié)果的坯沪。

4. 創(chuàng)造了一個Promise實例

var promise = new Promise( function( resolve, reject) {
/some code
if(//異步操作成功){
resolve(value);
}else{
reject(error);
}
});

5.Promise 方法:

Promise.prototype.then = function() {}
Promise.prototype.catch = function() {}
Promise.resolve = function() {}
Promise.reject = function() {}
Promise.all = function() {}
Promise.race = function() {}
1.promise.then方法返回promise的結(jié)果绿映,then 的第一個參數(shù)是處理正確時的返回值的函數(shù),第二個參數(shù)是處理錯誤時的返回的error的函數(shù)
promise.then(function(value) {
// success
}, function(error) {
// failure
});

  1. promise.catch可以捕獲promise返回的錯誤
    var promise = new Promise(function(resolve, reject) {
    throw new Error('test');
    });
    promise.catch(function(error) {
    console.log(error);
    });
  2. Promise.resolve 是將一個值包裹成 promise對象腐晾,狀態(tài)是fulfilled
    Promise.resolve('haha')
    等價于
    new Promise(function (resolve, reject) {resolve('haha')})
  3. Promise.reject 也是將一個值包裹成 promise對象叉弦,只不過狀態(tài)是 rejected
    5.Promise.all()用于將多個Promise實例,包裝成一個新的Promise實例藻糖。
    var promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('haha')
    }, 1000)
    })
    var promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('hehe')
    }, 2000)
    })
    var start = Date.now()
    Promise.all([promise1, promise2])
    .then((res) => {
    console.log(Date.now() - start)
    console.log(res)
    })
    (1)只有promise1淹冰、promise2的狀態(tài)都變成fulfilled,p的狀態(tài)才會變成fulfilled巨柒,此時promise1樱拴、promise2的返回值組成一個數(shù)組,傳遞給回調(diào)函數(shù)洋满。
    (2)只要promise1晶乔、promise2之中有一個被rejected,p的狀態(tài)就變成rejected牺勾,此時第一個被reject的實例的返回值正罢,會傳遞給新的Promise實例回調(diào)函數(shù)。
    6.Promise.race方法同樣是將多個Promise實例禽最,包裝成一個新的Promise實例。但是只要promise1袱饭、promise2之中有一個實例率先改變狀態(tài)川无,新的Promise實例的狀態(tài)就跟著改變。那個率先改變的 Promise 實例的返回值虑乖,就傳遞給新的Promise實例的回調(diào)函數(shù)。
    var promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('haha')
    }, 1000)
    })
    var promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('hehe')
    }, 2000)
    })
    var start = Date.now()
    Promise.race([promise1, promise2])
    .then((res) => {
    console.log(Date.now() - start)
    console.log(res)
    })
6.擴展
  1. then 方法可以被同一個 promise 調(diào)用多次,原理在于:第一次調(diào)用之前,狀態(tài)就已經(jīng)從pengding->fulfilled娱据,同時內(nèi)部保留了一個值房交,這時多次調(diào)用.then,都會返回內(nèi)部的那個值
    var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('haha')
    }, 1000)
    })
    var start = Date.now()
    promise.then((res) => {
    console.log(res, Date.now() - start)
    })
    promise.then((res) => {
    console.log(res, Date.now() - start)
    })
    promise.then((res) => {
    console.log(res, Date.now() - start)
    })
  2. 在Promise構(gòu)造函數(shù)里throw一個error糙捺,相當(dāng)于 reject(error)
  3. promise的 then和catch都是可以鏈式調(diào)用的诫咱,下一個then的值是上一個promise變成fulfilled的返回值(返回值可以是promise,也可以是任意值(這個任意值內(nèi)部是把它包裝成promise)。如果是promise洪灯,會等待該promise返回(狀態(tài)變更)),eg:
    var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('haha')
    }, 1000)
    })
    var start = Date.now()
    promise
    .then((res) => {
    console.log(res, Date.now() - start)
    })
    .then((res) => {
    console.log(res, Date.now() - start)
    return new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('hehe')
    }, 2000)
    })
    })
    .then((res) => {
    console.log(res, Date.now() - start)
    })
  4. 構(gòu)造函數(shù)resolve 或 reject 只執(zhí)行一次坎缭,多次調(diào)用沒有任何作用
    var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('haha')
    }, 1000)
    reject('error')
    })
    var start = Date.now()
    promise.then(() => {
    console.log('then', Date.now() - start)
    })
    promise.catch((e) => {
    console.error(e)
    console.error('catch', Date.now() - start)
    })
  5. 值穿透,then的參數(shù)正常情況下使用接收函數(shù),如果傳遞一個非函數(shù)掏呼,則忽略坏快,下一個then使用的是當(dāng)前then的上一個返回值,也就是會跳過這個then
    var promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
    reject('haha')
    }, 1000)
    })
    promise2
    .catch(1)
    .catch('hehe')
    .catch((error) => {
    return console.log(1, error)
    })
    .catch((error) => {
    return console.log(2, error)
    })
  6. promise拋錯(rejected)憎夷,則跳過then,被最近的一個catch捕獲(前提是:1.then沒有第二個處理錯誤的函數(shù) 2.最近的catch沒有值穿透)莽鸿,在then/catch里throw new Error(xxx)等價于return Promise.reject(xxx)
    Promise.resolve()
    .then(() => {
    // return new Error('error!!!') // 會打印1!J案O榈谩!
    return Promise.reject(new Error('error!!!'))
    })
    .then((res) => {
    console.log(1, res)
    })
    .catch((e) => {
    console.error(2, e)
    })
  7. then返回的值不能是 promise 本身鸣戴,否則會造成死循環(huán)啃沪,原因:then里返回的promise會等待他狀態(tài)改變(或者說執(zhí)行完)才會進入到下一個then
    var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('haha')
    }, 1000)
    })
    var a = promise.then(() => {
    return a
    })
    a.then(console.log)
    .catch(console.error)
  8. then方法的第二個參數(shù) vs catch方法, then里第二個處理錯誤的回調(diào)函數(shù)不會捕獲這個then第一個處理成功時的回調(diào)函數(shù)拋出的error窄锅,then/catch里沒有return值等價于return Promise.resolve(undefined)
    var promise = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve('haha')
    }, 1000)
    })
    promise
    .then(function success(res) {
    throw new Error('error')
    }, function fail1(e) {
    console.error(1, e)
    })
    .catch(function fail2(e) {
    console.error(2, e)
    })

三. Generator

1.Generator 函數(shù)是一個狀態(tài)機创千,封裝了多個內(nèi)部狀態(tài);執(zhí)行 Generator 函數(shù)會返回一個遍歷器對象入偷,返回的遍歷器對象追驴,可以依次遍歷 Generator 函數(shù)內(nèi)部的每一個狀態(tài)。
2.特點
  1. function關(guān)鍵字與函數(shù)名之間有一個星號
  2. 函數(shù)體內(nèi)部使用yield語句疏之,定義不同的內(nèi)部狀態(tài)(yield在英語里的意思就是“產(chǎn)出”)殿雪。
3.yield* 語句

由于Generator函數(shù)返回的遍歷器對象,只有調(diào)用next方法才會遍歷下一個內(nèi)部狀態(tài)锋爪,所以其實提供了一種可以暫停執(zhí)行的函數(shù)丙曙。yield語句就是暫停標(biāo)志。
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
(1)遇到y(tǒng)ield語句其骄,就暫停執(zhí)行后面的操作亏镰,并將緊跟在yield后面的那個表達式的值,作為返回的對象的value屬性值拯爽。
(2)下一次調(diào)用next方法時索抓,再繼續(xù)往下執(zhí)行,直到遇到下一個yield語句毯炮。
(3)如果沒有再遇到新的yield語句逼肯,就一直運行到函數(shù)結(jié)束,直到return語句為止桃煎,并將return語句后面的表達式的值篮幢,作為返回的對象的value屬性值。
(4)如果該函數(shù)沒有return語句为迈,則返回的對象的value屬性值為undefined洲拇。
(5)如果在 Generator 函數(shù)內(nèi)部奈揍,調(diào)用另一個 Generator 函數(shù),默認情況下是沒有效果的
function* foo() {
yield 'a';
yield 'b';
}
function* bar() {
yield 'x';
foo();
yield 'y';
}
for (let v of bar()){
console.log(v);
}
// "x"
// "y"

4.next()方法

hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }

  1. yield句本身沒有返回值赋续,或者說總是返回undefined男翰。
  2. 每次調(diào)用遍歷器對象的next方法,就會返回一個有著value和done兩個屬性的對象纽乱。value屬性表示當(dāng)前的內(nèi)部狀態(tài)的值蛾绎,是yield語句后面那個表達式的值;done屬性是一個布爾值鸦列,表示是否遍歷結(jié)束租冠。
  3. next方法可以帶一個參數(shù),該參數(shù)就會被當(dāng)作上一個yield語句的返回值薯嗤。
    function* f() {
    for(var i = 0; true; i++) {
    var reset = yield i;
    if(reset) { i = -1; }
    }
    }
    var g = f();
    g.next()
    // { value: 0, done: false }
    g.next()
    // { value: 1, done: false }
    g.next(true)
    // { value: 0, done: false }
5.for...of循環(huán)

for...of循環(huán)可以自動遍歷Generator函數(shù)時生成的Iterator對象顽爹,且此時不再需要調(diào)用next方法
function *foo() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
return 6;
}
for (let v of foo()) {
console.log(v);
}
// 1 2 3 4 5

6.Generator方法

Generator.prototype.throw()
Generator.prototype.return()

  1. throw()可以在函數(shù)體外拋出錯誤,然后在Generator函數(shù)體內(nèi)捕獲
    var g = function* () {
    try {
    yield;
    } catch (e) {
    console.log(e);
    }
    };
    var i = g();
    i.next();
    i.throw(new Error('出錯了骆姐!'));
    // Error: 出錯了镜粤!(…)
  2. return()返回給定的值,并且終結(jié)遍歷Generator函數(shù)
    function* gen() {
    yield 1;
    yield 2;
    yield 3;
    }
    var g = gen();
    g.next() // { value: 1, done: false }
    g.return('foo') // { value: "foo", done: true }
    g.next() // { value: undefined, done: true }
    如果return方法調(diào)用時玻褪,不提供參數(shù)肉渴,則返回值的value屬性為undefined
    function* gen() {
    yield 1;
    yield 2;
    yield 3;
    }
    var g = gen();
    g.next() // { value: 1, done: false }
    g.return() // { value: undefined, done: true }
7. co 模塊
  1. co 模塊是著名程序員 TJ Holowaychuk 于2013年6月發(fā)布的一個小工具,用于 Generator 函數(shù)的自動執(zhí)行
  2. 用法:
    Generator 函數(shù)只要傳入co函數(shù)带射,就會自動執(zhí)行同规;co函數(shù)返回一個Promise對象,因此可以用then方法添加回調(diào)函數(shù)
    var co = require('co');
    var gen = function* () {
    var f1 = yield readFile('/etc/fstab');
    var f2 = yield readFile('/etc/shells');
    console.log(f1.toString());
    console.log(f2.toString());
    };
    co(gen).then(function (){
    console.log('Generator 函數(shù)執(zhí)行完成');
    });
  3. 原理:
    自動執(zhí)行機制:當(dāng)異步操作有了結(jié)果窟社,能夠自動交回執(zhí)行權(quán)券勺。
    (1)回調(diào)函數(shù)。將異步操作包裝成 Thunk 函數(shù)灿里,在回調(diào)函數(shù)里面交回執(zhí)行權(quán)关炼。
    (2)Promise 對象。將異步操作包裝成 Promise 對象钠四,用then方法交回執(zhí)行權(quán)盗扒。

四. async (需要node@8以上)

  1. async 函數(shù)Generator 函數(shù)的語法糖:將 Generator 函數(shù)的星號(*)替換成async跪楞,將yield替換成await缀去,僅此而已。
    var fs = require('fs');
    var readFile = function (fileName) {
    return new Promise(function (resolve, reject) {
    fs.readFile(fileName, function(error, data) {
    if (error) reject(error);
    resolve(data);
    });
    });
    };
    var gen = function* () {
    var f1 = yield readFile('/etc/fstab');
    var f2 = yield readFile('/etc/shells');
    console.log(f1.toString());
    console.log(f2.toString());
    };
    寫成async函數(shù)甸祭,就是下面這樣缕碎。
    var asyncReadFile = async function () {
    var f1 = await readFile('/etc/fstab');
    var f2 = await readFile('/etc/shells');
    console.log(f1.toString());
    console.log(f2.toString());
    };
    2.用法:
    async function getStockPriceByName(name) {
    var symbol = await getStockSymbol(name);
    var stockPrice = await getStockPrice(symbol);
    return stockPrice;
    }
    getStockPriceByName('goog').then(function (result) {
    console.log(result);
    });
    (1)async函數(shù)返回一個 Promise 對象,可以使用then方法添加回調(diào)函數(shù)
    (2)async函數(shù)內(nèi)部return語句返回的值池户,會成為then方法回調(diào)函數(shù)的參數(shù)咏雌。
  2. await 命令
    async function f() {
    return await 123;
    }
    f().then(v => console.log(v)) // 123
    (1)wait 只能在 async 函數(shù)中使用
    (2)await命令后面是一個 Promise 對象凡怎。如果不是,會被轉(zhuǎn)成一個立即resolve的 Promise 對象赊抖。
    (3)只要一個await語句后面的 Promise 變?yōu)閞eject统倒,那么整個async函數(shù)都會中斷執(zhí)行。
    async function f() {
    await Promise.reject('出錯了');
    await Promise.resolve('hello world'); // 不會執(zhí)行
    }
  3. for await...of
    for await...of循環(huán)用于遍歷異步的 Iterator 接口
    async function f() {
    for await (const x of createAsyncIterable(['a', 'b'])) {
    console.log(x);
    }
    }
    // a
    // b
  4. Generator + co vs async + await
    (1)內(nèi)置執(zhí)行器氛雪。
    Generator 函數(shù)的執(zhí)行必須靠執(zhí)行器房匆,所以才有了co模塊,而async函數(shù)自帶執(zhí)行器报亩。也就是說浴鸿,async函數(shù)的執(zhí)行,與普通函數(shù)一模一樣弦追,只要一行岳链。
    (2)更好的語義。
    async和await劲件,比起星號和yield掸哑,語義更清楚了。async表示函數(shù)里有異步操作寇仓,await表示緊跟在后面的表達式需要等待結(jié)果举户。
    (3)更廣的適用性。
    co模塊約定遍烦,yield命令后面只能是 Thunk 函數(shù)或 Promise 對象俭嘁,而async函數(shù)的await命令后面,可以是Promise 對象和原始類型的值(數(shù)值服猪、字符串和布爾值供填,但這時等同于同步操作)。
    (4)返回值是 Promise罢猪。
    async函數(shù)的返回值是 Promise 對象近她,這比 Generator 函數(shù)的返回值是 Iterator 對象方便多了。你可以用then方法指定下一步的操作膳帕。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末粘捎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子危彩,更是在濱河造成了極大的恐慌攒磨,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件汤徽,死亡現(xiàn)場離奇詭異娩缰,居然都是意外死亡,警方通過查閱死者的電腦和手機谒府,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門拼坎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浮毯,“玉大人,你說我怎么就攤上這事泰鸡≌叮” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵盛龄,是天一觀的道長惦蚊。 經(jīng)常有香客問我,道長讯嫂,這世上最難降的妖魔是什么蹦锋? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮欧芽,結(jié)果婚禮上莉掂,老公的妹妹穿的比我還像新娘。我一直安慰自己千扔,他們只是感情好憎妙,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著曲楚,像睡著了一般厘唾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上龙誊,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天抚垃,我揣著相機與錄音,去河邊找鬼趟大。 笑死鹤树,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的逊朽。 我是一名探鬼主播罕伯,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼叽讳!你這毒婦竟也來了追他?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤岛蚤,失蹤者是張志新(化名)和其女友劉穎邑狸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灭美,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡推溃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年昂利,在試婚紗的時候發(fā)現(xiàn)自己被綠了届腐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铁坎。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖犁苏,靈堂內(nèi)的尸體忽然破棺而出硬萍,到底是詐尸還是另有隱情,我是刑警寧澤围详,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布朴乖,位于F島的核電站,受9級特大地震影響助赞,放射性物質(zhì)發(fā)生泄漏买羞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一雹食、第九天 我趴在偏房一處隱蔽的房頂上張望畜普。 院中可真熱鬧,春花似錦群叶、人聲如沸吃挑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舶衬。三九已至,卻和暖如春赎离,著一層夾襖步出監(jiān)牢的瞬間逛犹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工梁剔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留圾浅,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓憾朴,卻偏偏與公主長得像狸捕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子众雷,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

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

  • 一灸拍、Promise的含義 Promise在JavaScript語言中早有實現(xiàn),ES6將其寫進了語言標(biāo)準砾省,統(tǒng)一了用法...
    Alex灌湯貓閱讀 818評論 0 2
  • Promise 對象 Promise 的含義 Promise 是異步編程的一種解決方案鸡岗,比傳統(tǒng)的解決方案——回調(diào)函...
    neromous閱讀 8,698評論 1 56
  • 特點 Promise能將回調(diào)分離出來,在異步操作執(zhí)行之后,用鏈式方法執(zhí)行回調(diào),雖然es5用封裝函數(shù)也能實現(xiàn),但是如...
    一二三kkxx閱讀 616評論 0 1
  • 7月18日,7月的最后一個周末编兄,雖然天空下著雨轩性,卻阻擋不了愛學(xué)習(xí)的小伙們學(xué)習(xí)的腳步,安徽牛商會的各個企業(yè)在...
    合肥徽馬科技閱讀 374評論 0 0
  • 近來因著十分勞累狠鸳,又犯了眼疾揣苏,或曰干眼癥悯嗓,具體表現(xiàn)便是眼睛酸痛,總動不動便流下淚來卸察,有如賈誼那樣脯厨,所不同者,是賈長...
    競走的蝸牛閱讀 289評論 0 2