帶你玩轉 JavaScript ES6 (七) – 非同步

帶你玩轉 JavaScript ES6 (七) – 非同步

帶你玩轉 JavaScript ES6 (七) – 非同步

本文同步帶你玩轉 JavaScript ES6 (七) – 非同步,轉載請註明出處。

本章我們將學習 ES6 中的 Promise(非同步) 相關知識,瞭解如何使用 Promise 物件建立非同步程式

一、介紹

Promise 物件通過 new Promise(executor) 例項化建立,可以讓程式進入一個非同步的執行中,完成耗時的操作處理。

二、語法

2.1 例項化

語法:new Promise((resole, reject) => {})

Promise 類接收帶有兩個匿名函式作為引數的匿名函式,其中 resolve 表示成功處理函式,reject 表示失敗處理函式

let promise = new Promise((resole, reject) => {
console.log('main')
setTimeout(() => {
resole('run async')
}, 1500)
})

2.2 非同步成功執行處理方法

通過 Promise 物件的 then 方法繫結 resolve處理方法,可以通過鏈式操作繫結多個用於 resolve 的處理方法


let promise = new Promise((resole, reject) => {
console.log('main')
setTimeout(() => {
resole('run async')
}, 1500)
})
promise.then((msg) => {
console.log(msg);
})

上面示例會先列印輸出 mian,之後過 1.5 s 會列印輸出 run async 到控制檯。為了演示非同步執行,現在對上例稍作調整:

let promise = new Promise((resole, reject) => {
resole('run async')
console.log('main')
})
promise.then((msg) => {
console.log(msg);
})

我們首先將 resolve(‘run async’) 呼叫移至 console.log(‘main’) 之前。

如果是同步呼叫按照執行順序,會先輸出 run async 再輸出 main,但情況相反。說明 resolve 處理方法被非同步執行了。

2.3 非同步失敗執行處理方法

通過使用 Promise 物件的 catch 方法繫結 reject 處理方法。

let promise = new Promise((resole, reject) => {
//resole('run async')
reject('run async error')
console.log('main')
})
promise.then((msg) => {
throw new Error('error')
console.log(msg);
}).catch(() => {
console.log('error')
})

三、 Promise 生命週期

一個 Promise有以下幾種狀態:

pending: 初始狀態,既不是成功,也不是失敗狀態。
fulfilled: 意味著操作成功完成。
rejected: 意味著操作失敗。

pending 狀態的 Promise 物件可能觸發fulfilled 狀態並傳遞一個值給相應的狀態處理方法,也可能觸發失敗狀態(rejected)並傳遞失敗資訊。

當其中任一種情況出現時,Promise 物件的 then 方法繫結的處理方法(handlers )就會被呼叫(then方法包含兩個引數:onfulfilled 和 onrejected,它們都是 Function 型別。當Promise狀態為fulfilled時,呼叫 then 的 onfulfilled 方法,當Promise狀態為rejected時,呼叫 then 的 onrejected 方法, 所以在非同步操作的完成和繫結處理方法之間不存在競爭)。

注: Promise 生命週期相關內容引用自 Promise

四、使用 Promise 和 XHR 非同步載入圖片

這是 MDN 官方給出的示例,JavaScript 部分的程式碼如下

  function imgLoad(url) {
// Create new promise with the Promise() constructor;
// This has as its argument a function
// with two parameters, resolve and reject
return new Promise(function(resolve, reject) {
// Standard XHR to load an image
var request = new XMLHttpRequest();
request.open('GET', url);
request.responseType = 'blob';
// When the request loads, check whether it was successful
request.onload = function() {
if (request.status === 200) {
// If successful, resolve the promise by passing back the request response
resolve(request.response);
} else {
// If it fails, reject the promise with a error message
reject(Error('Image didn\'t load successfully; error code:'   request.statusText));
}
};
request.onerror = function() {
// Also deal with the case when the entire request fails to begin with
// This is probably a network error, so reject the promise with an appropriate message
reject(Error('There was a network error.'));
};
// Send the request
request.send();
});
}
// Get a reference to the body element, and create a new image object
var body = document.querySelector('body');
var myImage = new Image();
// Call the function with the URL we want to load, but then chain the
// promise then() method on to the end of it. This contains two callbacks
imgLoad('myLittleVader.jpg').then(function(response) {
// The first runs when the promise resolves, with the request.response
// specified within the resolve() method.
var imageURL = window.URL.createObjectURL(response);
myImage.src = imageURL;
body.appendChild(myImage);
// The second runs when the promise
// is rejected, and logs the Error specified with the reject() method.
}, function(Error) {
console.log(Error);
});