1、什么是Promise
ajax
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最先提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。 所谓Promise,简单说就是一个容器,里面保存着某个将来才会结束的事件(一般是一个异步操做)的结果。编程
从语法上说,Promise 是一个对象,从它能够获取异步操做的消息。Promise 提供统一的 API,各类异步操做均可以用一样的方法进行处理。promise
如下是MDN对Promise的定义异步
The Promise object is used for asynchronous computations. A Promise represents a single asynchronous operation that hasn't completed yet, but is expected in the future. async
译文:Promise对象用于异步操做,它表示一个还没有完成且预计在将来完成的异步操做。异步编程
2、同步和异步函数
咱们知道,JavaScript的执行环境是「单线程」。 spa
所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它会「阻塞」其余任务。这个任务可称为主线程。 线程
但实际上还有其余线程,如事件触发线程、ajax请求线程等。 这也就引起了同步和异步的问题。 对象
同步:
while(true);
console.log("don't execute"); //不会执行
异步:
setTimeout(function() {
console.log('taskA, asynchronous');
}, 0);
console.log('taskB, synchronize');
3、回调函数
回调函数是一段可执行的代码段,它以「参数」的形式传递给其余代码,在其合适的时间执行这段(回调函数)的代码。
var friends = ["Mike", "Stacy", "Andy", "Rick"];
friends.forEach(function (eachName, index){
console.log(index + 1 + ". " + eachName); // 1. Mike, 2. Stacy, 3. Andy, 4. Rick
});
上面例子中的setTimeout就是一个回调函数
再看一次:
setTimeout(function() {
console.log('taskA, asynchronous');
}, 0);
console.log('taskB, synchronize');
4、为何使用Promise
使用上面的回调函数的方式,若是回调函数嵌套不少层,很容易陷入回调地狱,代码可读性差
function fn(callback1, callback2) {
// 耗时操做 let a = 0
for (let i = 0; i < 100; i++) {
a++
}
setTimeout(function() {
callback1(++a)
setTimeout(function() {
callback2(++a)
}, 0)
}, 0)
}
function fn1(a) {
console.log(a)
}
function fn2(a) {
console.log(a)
}
fn(fn1, fn2)
5、Promise基本概念
Promise对象表明一个未完成、但预计未来会完成的操做。
ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。
Promise构造函数接受一个函数做为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用本身部署。
resolve函数的做用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操做成功时调用,并将异步操做的结果,做为参数传递出去;
reject函数的做用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操做失败时调用,并将异步操做报出的错误,做为参数传递出去。
它有如下三种状态:
pending:初始值,不是fulfilled,也不是rejected
fulfilled:表明操做成功
rejected:表明操做失败
Promise有两种状态改变的方式,既能够从pending转变为fulfilled,也能够从pending转变为rejected。
一旦状态改变,就「凝固」了,会一直保持这个状态,不会再发生变化。
当状态发生变化,promise.then绑定的函数就会被调用。
注意:Promise一旦新建就会「当即执行」,没法取消。
6、Promise基本用法
下面代码创造了一个Promise实例。
const promise = new Promise(
// executor
function(resolve, reject) {
if (/* 异步操做成功 */){
resolve(value);
} else {
reject(error);
}
});
executor是带有 resolve 和 reject 两个参数的函数 。Promise构造函数执行时当即调用executor 函数, resolve 和 reject 两个函数做为参数传递给executor(executor 函数在Promise构造函数返回所建promise实例对象前被调用)。resolve 和 reject 函数被调用时,分别将promise的状态改成fulfilled(完成)或rejected(失败)。executor 内部一般会执行一些异步操做,一旦异步操做执行完毕(可能成功/失败),要么调用resolve函数来将promise状态改为fulfilled,要么调用reject 函数将promise的状态改成rejected。
Promise实例生成之后,能够用then方法分别指定resolved状态和rejected状态的回调函数。
promise.then(function(value) { // success }, function(error) { // failure }); then方法能够接受两个回调函数做为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不必定要提供。这两个函数都接受Promise对象传出的值做为参数。
7、Promise实例应用
//简单的promise
const promise1 = new Promise(
// executor
function(resolve, reject) {
if (false){
resolve('request success');
} else {
reject('request error');
}
});
promise.then(function(value) {
console.log(value);
}, function(error) {
console.log(error);
});
//then只传一个方法的状况
const promise2 = new Promise(
// executor
function(resolve, reject) {
if (false){
resolve('request success');
} else {
reject('request error');
}
});
promise2.then(function(value) {
console.log(value);
});
promise2.catch(function(error) {
console.log(error);
});
//链式调用
const promise3 = new Promise(
// executor
function(resolve, reject) {
if (false){
resolve('request success');
} else {
reject('request error');
}
}).then(function(value) {
console.log(value);
}).catch(function(error) {
console.log(error);
});
//嵌套调用
const promise4 = new Promise(
// executor
function(resolve, reject) {
if (true){
resolve('request success');
} else {
reject('request error');
}
}).then(function(value) {
const nextPromise = new Promise(
function(resolve, reject) {
resolve('next request success');
});
return nextPromise;
}).then(function(value) {
console.log(value);
}).catch(function(error){
console.log(error);
});