带你玩转 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);
});