91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript之promise_動力節點Java學院整理

發布時間:2020-09-25 01:21:58 來源:腳本之家 閱讀:167 作者:liaoxuefeng 欄目:web開發

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

由于這個“缺陷”,導致JavaScript的所有網絡操作,瀏覽器事件,都必須是異步執行。異步執行可以用回調函數實現:

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

觀察上述代碼執行,在Chrome的控制臺輸出可以看到:

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

可見,異步操作會在將來的某個時間點觸發一個函數調用。
AJAX就是典型的異步操作。以上一節的代碼為例:

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

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

有沒有更好的寫法?比如寫成這樣:

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

這種鏈式寫法的好處在于,先統一執行AJAX邏輯,不關心如何處理結果,然后,根據結果是成功還是失敗,在將來的某個時候調用success函數或fail函數。

古人云:“君子一諾千金”,這種“承諾將來會執行”的對象在JavaScript中稱為Promise對象。

Promise有各種開源實現,在ES6中被統一規范,由瀏覽器直接支持。先測試一下你的瀏覽器是否支持Promise:

'use strict';

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

我們先看一個最簡單的Promise例子:生成一個0-2之間的隨機數,如果小于1,則等待一段時間后返回成功,否則返回失敗:

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);
}

這個test()函數有兩個參數,這兩個參數都是函數,如果執行成功,我們將調用resolve('200 OK'),如果執行失敗,我們將調用reject('timeout in ' + timeOut + ' seconds.')。可以看出,test()函數只關心自身的邏輯,并不關心具體的resolve和reject將如何處理結果。
有了執行函數,我們就可以用一個Promise對象來執行它,并在將來某個時刻獲得成功或失敗的結果:

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

變量p1是一個Promise對象,它負責執行test函數。由于test函數在內部是異步執行的,當test函數執行成功時,我們告訴Promise對象:

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

當test函數執行失敗時,我們告訴Promise對象:

p2.catch(function (reason) {
 console.log('失敗:' + reason);
});

Promise對象可以串聯起來,所以上述代碼可以簡化為:

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

實際測試一下,看看Promise是如何異步執行的:

'use strict';

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

// 輸出log到頁面:
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

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

JavaScript之promise_動力節點Java學院整理

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

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

其中,job1、job2和job3都是Promise對象。
下面的例子演示了如何串行執行一系列需要異步計算獲得結果的任務:

'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的計算結果:
function multiply(input) {
 return new Promise(function (resolve, reject) {
  log('calculating ' + input + ' x ' + input + '...');
  setTimeout(resolve, 500, input * input);
 });
}

// 0.5秒后返回input+input的計算結果:
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可以看成一個模擬網絡等異步執行的函數。現在,我們把上一節的AJAX異步執行函數轉換為Promise對象,看看用Promise如何簡化異步處理:

'use strict';

// ajax函數將返回Promise對象:
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成功,獲得響應內容
 log.innerText = text;
}).catch(function (status) { // 如果AJAX失敗,獲得響應代碼
 log.innerText = 'ERROR: ' + status;
});

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

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

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

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執行較快,Promise的then()將獲得結果'P1'。p2仍在繼續執行,但執行結果將被丟棄。

如果我們組合使用Promise,就可以把很多異步任務以并行和串行的方式組合起來執行。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

昌吉市| 萝北县| 如东县| 开鲁县| 讷河市| 沁水县| 固原市| 台中市| 孝昌县| 漳州市| 泽库县| 德安县| 正定县| 深圳市| 运城市| 罗定市| 武清区| 惠安县| 富宁县| 河北区| 沅陵县| 堆龙德庆县| 宜兴市| 永顺县| 凯里市| 龙南县| 塔河县| 阿城市| 滦南县| 南皮县| 时尚| 晴隆县| 石楼县| 隆化县| 天津市| 丰宁| 新丰县| 阳泉市| 左贡县| 清流县| 扎囊县|