最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript之promise_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

 更新時(shí)間:2017年07月03日 11:13:07   作者:liaoxuefeng  
這篇文章主要為大家詳細(xì)介紹了JavaScript之promise的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

在JavaScript的世界中,所有代碼都是單線程執(zhí)行的。

由于這個(gè)“缺陷”,導(dǎo)致JavaScript的所有網(wǎng)絡(luò)操作,瀏覽器事件,都必須是異步執(zhí)行。異步執(zhí)行可以用回調(diào)函數(shù)實(shí)現(xiàn):

function callback() {
 console.log('Done');
}
console.log('before setTimeout()');
setTimeout(callback, 1000); // 1秒鐘后調(diào)用callback函數(shù)
console.log('after setTimeout()');

觀察上述代碼執(zhí)行,在Chrome的控制臺(tái)輸出可以看到:

before setTimeout()
after setTimeout()
(等待1秒后)
Done

可見(jiàn),異步操作會(huì)在將來(lái)的某個(gè)時(shí)間點(diǎn)觸發(fā)一個(gè)函數(shù)調(diào)用。
AJAX就是典型的異步操作。以上一節(jié)的代碼為例:

request.onreadystatechange = function () {
 if (request.readyState === 4) {
  if (request.status === 200) {
   return success(request.responseText);
  } else {
   return fail(request.status);
  }
 }
}

把回調(diào)函數(shù)success(request.responseText)和fail(request.status)寫到一個(gè)AJAX操作里很正常,但是不好看,而且不利于代碼復(fù)用。

有沒(méi)有更好的寫法?比如寫成這樣:

var ajax = ajaxGet('http://...');
ajax.ifSuccess(success)
 .ifFail(fail);

這種鏈?zhǔn)綄懛ǖ暮锰幵谟?,先統(tǒng)一執(zhí)行AJAX邏輯,不關(guān)心如何處理結(jié)果,然后,根據(jù)結(jié)果是成功還是失敗,在將來(lái)的某個(gè)時(shí)候調(diào)用success函數(shù)或fail函數(shù)。

古人云:“君子一諾千金”,這種“承諾將來(lái)會(huì)執(zhí)行”的對(duì)象在JavaScript中稱為Promise對(duì)象。

Promise有各種開源實(shí)現(xiàn),在ES6中被統(tǒng)一規(guī)范,由瀏覽器直接支持。先測(cè)試一下你的瀏覽器是否支持Promise:

'use strict';

new Promise(function () {});
// 直接運(yùn)行測(cè)試:
alert('支持Promise!');

我們先看一個(gè)最簡(jiǎn)單的Promise例子:生成一個(gè)0-2之間的隨機(jī)數(shù),如果小于1,則等待一段時(shí)間后返回成功,否則返回失?。?br />

function test(resolve, reject) {
 var timeOut = Math.random() * 2;
 log('set timeout to: ' + timeOut + ' seconds.');
 setTimeout(function () {
  if (timeOut < 1) {
   log('call resolve()...');
   resolve('200 OK');
  }
  else {
   log('call reject()...');
   reject('timeout in ' + timeOut + ' seconds.');
  }
 }, timeOut * 1000);
}

這個(gè)test()函數(shù)有兩個(gè)參數(shù),這兩個(gè)參數(shù)都是函數(shù),如果執(zhí)行成功,我們將調(diào)用resolve('200 OK'),如果執(zhí)行失敗,我們將調(diào)用reject('timeout in ' + timeOut + ' seconds.')??梢钥闯?,test()函數(shù)只關(guān)心自身的邏輯,并不關(guān)心具體的resolve和reject將如何處理結(jié)果。
有了執(zhí)行函數(shù),我們就可以用一個(gè)Promise對(duì)象來(lái)執(zhí)行它,并在將來(lái)某個(gè)時(shí)刻獲得成功或失敗的結(jié)果:

var p1 = new Promise(test);
var p2 = p1.then(function (result) {
 console.log('成功:' + result);
});
var p3 = p2.catch(function (reason) {
 console.log('失?。? + reason);
});

變量p1是一個(gè)Promise對(duì)象,它負(fù)責(zé)執(zhí)行test函數(shù)。由于test函數(shù)在內(nèi)部是異步執(zhí)行的,當(dāng)test函數(shù)執(zhí)行成功時(shí),我們告訴Promise對(duì)象:

// 如果成功,執(zhí)行這個(gè)函數(shù):
p1.then(function (result) {
 console.log('成功:' + result);
});

當(dāng)test函數(shù)執(zhí)行失敗時(shí),我們告訴Promise對(duì)象:

p2.catch(function (reason) {
 console.log('失?。? + reason);
});

Promise對(duì)象可以串聯(lián)起來(lái),所以上述代碼可以簡(jiǎn)化為:

new Promise(test).then(function (result) {
 console.log('成功:' + result);
}).catch(function (reason) {
 console.log('失敗:' + reason);
});

實(shí)際測(cè)試一下,看看Promise是如何異步執(zhí)行的:

'use strict';

// 清除log:
var logging = document.getElementById('test-promise-log');
while (logging.children.length > 1) {
 logging.removeChild(logging.children[logging.children.length - 1]);
}

// 輸出log到頁(yè)面:
function log(s) {
 var p = document.createElement('p');
 p.innerHTML = s;
 logging.appendChild(p);
}
new Promise(function (resolve, reject) {
 log('start new Promise...');
 var timeOut = Math.random() * 2;
 log('set timeout to: ' + timeOut + ' seconds.');
 setTimeout(function () {
  if (timeOut < 1) {
   log('call resolve()...');
   resolve('200 OK');
  }
  else {
   log('call reject()...');
   reject('timeout in ' + timeOut + ' seconds.');
  }
 }, timeOut * 1000);
}).then(function (r) {
 log('Done: ' + r);
}).catch(function (reason) {
 log('Failed: ' + reason);
});

Log:

start new Promise...
set timeout to: 0.5354042750614991 seconds.
call resolve()...
Done: 200 OK

可見(jiàn)Promise最大的好處是在異步執(zhí)行的流程中,把執(zhí)行代碼和處理結(jié)果的代碼清晰地分離了:

Promise還可以做更多的事情,比如,有若干個(gè)異步任務(wù),需要先做任務(wù)1,如果成功后再做任務(wù)2,任何任務(wù)失敗則不再繼續(xù)并執(zhí)行錯(cuò)誤處理函數(shù)。
要串行執(zhí)行這樣的異步任務(wù),不用Promise需要寫一層一層的嵌套代碼。有了Promise,我們只需要簡(jiǎn)單地寫:

job1.then(job2).then(job3).catch(handleError);

其中,job1、job2和job3都是Promise對(duì)象。
下面的例子演示了如何串行執(zhí)行一系列需要異步計(jì)算獲得結(jié)果的任務(wù):

'use strict';

var logging = document.getElementById('test-promise2-log');
while (logging.children.length > 1) {
 logging.removeChild(logging.children[logging.children.length - 1]);
}

function log(s) {
 var p = document.createElement('p');
 p.innerHTML = s;
 logging.appendChild(p);
}
// 0.5秒后返回input*input的計(jì)算結(jié)果:
function multiply(input) {
 return new Promise(function (resolve, reject) {
  log('calculating ' + input + ' x ' + input + '...');
  setTimeout(resolve, 500, input * input);
 });
}

// 0.5秒后返回input+input的計(jì)算結(jié)果:
function add(input) {
 return new Promise(function (resolve, reject) {
  log('calculating ' + input + ' + ' + input + '...');
  setTimeout(resolve, 500, input + input);
 });
}

var p = new Promise(function (resolve, reject) {
 log('start new Promise...');
 resolve(123);
});

p.then(multiply)
 .then(add)
 .then(multiply)
 .then(add)
 .then(function (result) {
 log('Got value: ' + result);
});

Log:

start new Promise...
calculating 123 x 123...
calculating 15129 + 15129...
calculating 30258 x 30258...
calculating 915546564 + 915546564...
Got value: 1831093128

setTimeout可以看成一個(gè)模擬網(wǎng)絡(luò)等異步執(zhí)行的函數(shù)?,F(xiàn)在,我們把上一節(jié)的AJAX異步執(zhí)行函數(shù)轉(zhuǎn)換為Promise對(duì)象,看看用Promise如何簡(jiǎn)化異步處理:

'use strict';

// ajax函數(shù)將返回Promise對(duì)象:
function ajax(method, url, data) {
 var request = new XMLHttpRequest();
 return new Promise(function (resolve, reject) {
  request.onreadystatechange = function () {
   if (request.readyState === 4) {
    if (request.status === 200) {
     resolve(request.responseText);
    } else {
     reject(request.status);
    }
   }
  };
  request.open(method, url);
  request.send(data);
 });
}
var log = document.getElementById('test-promise-ajax-result');
var p = ajax('GET', '/api/categories');
p.then(function (text) { // 如果AJAX成功,獲得響應(yīng)內(nèi)容
 log.innerText = text;
}).catch(function (status) { // 如果AJAX失敗,獲得響應(yīng)代碼
 log.innerText = 'ERROR: ' + status;
});

除了串行執(zhí)行若干異步任務(wù)外,Promise還可以并行執(zhí)行異步任務(wù)。
試想一個(gè)頁(yè)面聊天系統(tǒng),我們需要從兩個(gè)不同的URL分別獲得用戶的個(gè)人信息和好友列表,這兩個(gè)任務(wù)是可以并行執(zhí)行的,用Promise.all()實(shí)現(xiàn)如下:

var p1 = new Promise(function (resolve, reject) {
 setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
 setTimeout(resolve, 600, 'P2');
});
// 同時(shí)執(zhí)行p1和p2,并在它們都完成后執(zhí)行then:
Promise.all([p1, p2]).then(function (results) {
 console.log(results); // 獲得一個(gè)Array: ['P1', 'P2']
});

有些時(shí)候,多個(gè)異步任務(wù)是為了容錯(cuò)。比如,同時(shí)向兩個(gè)URL讀取用戶的個(gè)人信息,只需要獲得先返回的結(jié)果即可。這種情況下,用Promise.race()實(shí)現(xiàn):

var p1 = new Promise(function (resolve, reject) {
 setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
 setTimeout(resolve, 600, 'P2');
});
Promise.race([p1, p2]).then(function (result) {
 console.log(result); // 'P1'
});

由于p1執(zhí)行較快,Promise的then()將獲得結(jié)果'P1'。p2仍在繼續(xù)執(zhí)行,但執(zhí)行結(jié)果將被丟棄。

如果我們組合使用Promise,就可以把很多異步任務(wù)以并行和串行的方式組合起來(lái)執(zhí)行。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

南靖县| 太湖县| 正镶白旗| 恩施市| 浦东新区| 长治市| 葫芦岛市| 高碑店市| 邵阳县| 沧州市| 浮梁县| 蓝山县| 纳雍县| 哈巴河县| 顺平县| 丰都县| 盈江县| 望谟县| 茌平县| 射洪县| 南通市| 黑河市| 株洲县| 兴义市| 威海市| 宜阳县| 克什克腾旗| 东乌珠穆沁旗| 葫芦岛市| 金秀| 甘肃省| 定襄县| 云霄县| 固镇县| 哈密市| 建宁县| 甘谷县| 东乡族自治县| 彭山县| 苍梧县| 吴旗县|