记录ES6中Promise的使用。
ES6的Promise对象使用小记。
在使用axios中,经常看到 Promise 对象,本文做个小记录。
Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及该异步操作的结果值,本质上,Promise 是一个绑定了回调的对象,而不是将回调传进函数内部。
语法
1
new Promise( function(resolve, reject) {...} /* executor */ );
参数说明:
executor 是带有 resolve 和 reject 两个参数的函数 。Promise 构造函数执行时立即调用 executor 函数, resolve 和 reject 两个函数作为参数传递给 executor(executor 函数在 Promise 构造函数返回所建 promise 实例对象前被调用)。resolve 和 reject 函数被调用时,分别将 promise的状态改为fulfilled(完成)或 rejected(失败)。executor 内部通常会执行一些异步操作,一旦异步操作执行完毕(可能成功/失败),要么调用 resolve 函数来将 promise 状态改成 fulfilled,要么调用 reject 函数将 promise 的状态改为 rejected。如果在 executor 函数中抛出一个错误,那么该 promise 状态为 rejected。executor 函数的返回值被忽略。
常规使用方法
resolve
1
2
3
4
5
6
7
8
var pmise = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve("delay completed");
}, 500);
});
pmise.then(function(msg) {
alert(msg);
});
在500ms之后会执行alert(“deley complted”)。
reject
1
2
3
4
5
6
7
8
9
var pmise = new Promise(function(resolve, reject) {
setTimeout(() => {
reject("sorry, error occurred!");
}, 1000);
});
pmise.catch(function(error) {
alert(error);
});
catch
catch 可以指定 reject 的回调,它还有另外一个作用:在执行 resolve 的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。
finally
方法返回一个 Promise,在 promise 执行结束时,无论结果是 fulfilled 或者是 rejected,在执行 then() 和 catch() 后,都会执行 finally 指定的回调函数。这为指定执行完 promise 后,无论结果是 fulfilled 还是 rejected 都需要执行的代码提供了一种方式,避免同样的语句需要在 then() 和 catch() 中各写一次的情况。
1
2
3
4
5
6
7
8
9
10
var pmise = new Promise(function(resolve, reject) {
setTimeout(() => {
reject("sorry, error occurred!");
}, 1000);
});
pmise.then(xxx)
.catch(xxx)
.finally(() => {
//取消进度条等
})
描述
Promise 对象是一个代理对象(代理一个值),被代理的值在 Promise 对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的 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 对象是由关键字 new 及其构造函数来创建的。该构造函数会把一个叫做 “处理器函数”(executor function)的函数作为它的参数。这个“处理器函数”接受两个函数—— resolve 和 reject ——作为其参数。当异步任务顺利完成且返回结果值时,会调用 resolve 函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用 reject 函数。
1
2
3
4
5
6
7
let pmise = new Promise((resolve, reject) => {
// ?做一些异步操作,最终会调用下面两者之一:
//
// resolve(someValue); // fulfilled
// ?或
// reject("failure reason"); // rejected
})
结合其他函数使用:
1
2
3
4
5
6
7
8
9
function simplePromise() {
return new Promise((resolve, reject) => {
cost xhr = new XMLHttpRequest();
xhr.open("xxx");
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(xhr.statusText);
xhr.send();
})
}
链式调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
clickBtn() {
this.asyncA().then(obj => {
alert(obj);
return this.asyncB();
}).then(obj => {
alert(obj);
}).catch(reason => {
alert(reason);
})
},
asyncA() {
return new Promise((res, rej) => {
setTimeout(() => {
res("asyncA completed");
}, 1000);
});
},
asyncB() {
return new Promise((res, rej) => {
setTimeout(() => {
res("asyncB completed");
}, 1000);
});
}
Promise.all(iterable)
这个方法返回一个新的 promise 对象,该 promise 对象在 iterable 参数对象里所有的 promise 对象都成功的时候才会触发成功,一旦有任何一个 iterable 里面的 promise 对象失败则立即触发该 promise 对象的失败。这个新的 promise 对象在触发成功状态以后,会把一个包含 iterable 里所有 promise 返回值的数组作为成功回调的返回值,顺序跟 iterable 的顺序保持一致;如果这个新的 promise 对象触发了失败状态,它会把 iterable 里第一个触发失败的 promise 对象的错误信息作为它的失败错误信息。Promise.all 方法常被用于处理多个 promise 对象的状态集合。
此实例在 iterable 参数内所有的 promise 都“ 完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。
1
2
3
4
5
6
7
8
9
var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then(values => {
console.log(values);
});
输出:
Array [3, 42, “foo”]
Promise.race(iterable)
当 iterable 参数里的任意一个子 promise 被成功或失败后,父 promise 马上也会用子 promise 的成功返回值或失败详情作为参数调用父 promise 绑定的相应句柄,并返回该 promise 对象。
可以理解为一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝。
1
2
3
4
5
6
7
8
9
10
11
12
var promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'one');
});
var promise2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then(function(value) {
console.log(value);
// Both resolve, but promise2 is faster
});
上面只会输出:
two
Promise.resolve(value)
返回一个以给定值解析后的 Promise 对象。但如果这个值是个 thenable(即带有then方法),返回的 promise 会“跟随”这个 thenable 的对象,采用它的最终状态(指resolved/rejected/pending/settled);如果传入的 value 本身就是 promise 对象,则该对象作为 Promise.resolve 方法的返回值返回;否则以该值为成功状态返回 promise 对象。
1
2
3
4
5
var promise1 = Promise.resolve(123);
promise1.then(value => {
console.log(value);
});
1
2
3
4
5
Promise.resolve("Success").then(value => {
console.log(value); // "Success"
}, reason => {
// 不会被调用
});
1
2
3
4
var p = Promise.resolve([1,2,3]);
p.then(v => {
console.log(v[0]); // 1
});
Resolve另一个promise对象
1
2
3
4
5
6
7
8
9
10
11
12
var original = Promise.resolve('我在第二行');
var cast = Promise.resolve(original);
cast.then(function(value) {
console.log('value: ' + value);
});
console.log('original === cast ? ' + (original === cast));
/*
* 打印顺序如下,这里有一个同步异步先后执行的区别
* original === cast ? true
* value: 我在第二行
*/
Promise.reject(reason)
该方法返回一个带有拒绝原因 reason 参数的 Promise 对象。
1
2
3
4
5
Promise.reject(new Error("fail")).then(result => {
// 未被调用
}, error => {
console.log(error); // stacktrace
});
详细说明参见Promise。