很久没写博客了......看了很多关于Promise的文章,但是感觉也不是很理解,没办法去就看视频了。偶然发现慕课里有个关于Promise的视频,然后今天看了前两章,顺便整理了下笔记,记录下吧~
Promise
是什么?
-
用于异步计算。
-
可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果。
-
可以在对象之间传递和操作Promise,帮助我们处理队列。
产生的原因
-
JavaScript包含大量的异步操作(AB工作的完成顺序,和交付他们时间顺序无关)
-
异步操作的常见语法
-
事件侦听和响应
-
回调
-
-
常见异步事件(浏览器中的JavaScript)
-
异步操作以事件为主
-
回调主要出现在Ajax和File API
-
-
Node.js是无阻塞高并发、依赖大量回调函数
异步回调的问题
-
嵌套层次很深,容易陷入回调地狱,使得代码难以维护。
-
无法正常使用return和throw。
-
无法正常检索堆栈信息。
-
多个回调之间难以建立联系。
ps:
-
因为异步回调函数处于新的栈中,在此栈中无法获取之前的栈的信息,之前的栈也无法获取此栈中的错误,因此try和catch是无法生效的。
-
因为无法判断异步执行顺序,只能在外层作用域声明大量的变量供内层作用域使用,导致这些变量有可能会被其他函数访问和修改,从而导致错误。
Promise详解
创建过程:
-
初始化Promise实例。
-
在实例中传入参数,该参数是一个函数(执行器)。
-
执行器拥有两个参数:resolve、reject。
-
成功调用resolve方法,失败调用reject方法。不同的方法执行完会改变Promise实例的状态。
-
执行then方法中对应的函数。
new Promise(
/* 执行器 executor */
function(resolve, reject) {
// 一段耗时很长的异步操作
resolve(); // 数据处理完成
reject(); // 数据处理出错
}
)
.then(function A() {
// 成功,下一步
}, function B() {
// 失败,做相应处理
});
理解:
-
Promise是一个代理对象,它和原先要进行的操作并无关系。
-
它通过引入的一个回调,避免更多的回调。
-
Promise状态发生改变,就会触发.then()里的响应函数处理后续步骤。
-
Promise状态一经改变,不会再变。
-
Promise实例一经创建,执行器立即执行。
Promise的三个状态
-
pending【待定】初始状态 —— 实例化
-
fulfilled【实现】操作成功 —— 调用resolve
-
rejected【被否决】操作失败 —— 调用reject
简单范例
定时执行
console.log('here we go');
new Promise( resolve => {
setTimeout( () => {
resolve('hello');
},2000);
})
.then( value => {
console.log(value + ' world');
})
//输出结果
// here we go
/*
Promise {
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: undefined
}
*/
// 两秒后
// hello world
执行顺序:先输出‘here we go’,接着执行定时器,两秒后将‘hello’传给.then()函数,输出‘hello, world'
两步执行(常用)
console.log('here we go');
new Promise( resolve => {
setTimeout( () => {
resolve('hello');
}, 2000);
})
.then ( value => {
console.log( value );
return new Promise( resolve => {
setTimeout( () => {
resolve('world');
}, 2000);
});
})
.then ( value => {
console.log( value + ' world');
});
//输出结果
// here we go
/*
Promise {
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: undefined
}
*/
// 两秒后
// hello
// 两秒后
// world world
执行顺序:
先输出‘here we go',接着进入执行器,两秒后将'hello’传给第一个.then()函数;
第一个.then()函数输出‘hello',返回一个新的Promise;
新的Promise中开始执行器,两秒后将’world'传给‘第二个then函数;
第二个.then()函数输出’world world'。
对已完成的Promise执行.then()
console.log('start');
let promise = new Promise( resolve => {
setTimeout( () => {
console.log('the promise fulfilled');
resolve('hello, world');
}, 1000);
});
setTimeout( () => {
promise.then( value => {
console.log(value);
})
}, 3000)
//输出结果
// start
/*
Promise {
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: undefined
}
*/
// the promise fulfilled
// 1秒后
// 两秒后
// hello, world
执行顺序:先输出‘start’,接着两个定时器同时执行,一秒后输出'the promise fulfilled',并将‘hello, world'传出;再过两秒,执行.then(),输出’hello, world'。
promise队列的重要特性
在任何地方生成了一个promise队列之后,我们可以把它作为一个变量进行床底,如果我们的操作是队列的状态,即先进先出的状态,就可以在后面追加任意多的.then(),不管之前的队列是完成还是没有完成,队列都会按照固定的顺序完成。(下个例子更形象)
在.then()函数里面不返回新的Promise(并不影响.then()的执行)
console.log('here we go');
new Promise( resolve => {
setTimeout( () => {
resolve('hello');
}, 2000);
})
.then( value => {
console.log(value);
console.log('everyone');
(function() {
return new Promise( resolve => {
setTimeout( () => {
console.log('Mr.Laurence');
resolve('Merry Xmas');
}, 2000);
});
}());
return false;
})
.then( value => {
console.log( value + ' world');
})
//输出结果
// here we go
/*
Promise {
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: undefined
}
*/
// 两秒后
// hello
// everyone
// false world
// 两秒后
// Mr.Laurence
执行顺序:
输出‘here we go',进入Promise实例中,两秒后将’hello‘传给第一个.then();
第一个.then()输出’hello',接着输出‘everyone',接着执行立即执行函数。在此同时第一个.then()返回false,即将false传给第二个.then();
第二个.then()输出’false world';(如果注释掉return false,则输出'undefined world',可见返回结果不影响Promise继续往下执行)
在第一个.then()返回false后的两秒,输出'Mr.Lanrence'。
.then()
-
.then()接受两个函数作为参数,分别代表fulfilled和rejected
-
.then()返回一个新的Promise实例,所以它可以链式调用
-
当前面的Promise状态改变时,.then()根据其最终状态,选择特定的状态响应函数执行
-
状态响应函数可以返回新的Promise,或者其他值
-
如果返回新的Promise,那么下一级.then()会在新Promise状态改变之后执行
-
如果返回的是其他任何值,则会立即执行下一级.then()
console.log('start');
new Promise(resolve => {
console.log('Step 1');
setTimeout(() => {
resolve(100);
}, 1000);
})
.then(value => {
return new Promise(resolve => {
console.log('Step 1-1');
setTimeout(() => {
resolve(110);
}, 1000);
})
})
.then(value => {
console.log('Step 1-2');
return value;
})
.then(value => {
console.log('Step 1-3');
return value;
})
.then(value => {
console.log(value);
console.log('Step 2');
})
// 输出
// start
// Step 1
// 一秒后
// Step 1-1
// Step 1-2
// Step 1-3
// 110
// Step 2