Promise新建后就会立即执行!!!
一、箭头函数
箭头函数 是在es6 中添加的一种规范。
x => x * x 相当于 function(x){return x*x}
x => x * x
//相当于
function(x)
{
return x*x
}
箭头函数相当于 匿名函数, 简化了函数的定义。 语言的发展都是倾向于简洁 对人类友好的, 减轻工作量的。
// 两个参数返回后面的值
(x, y) =>x*y + y*y
//没有参数
() => 999
// 可变参数
(x, y, ...rest) =>{
var i,sum = x+y;
for (i=0;i<rest.length;i++){
sum += rest[i];
}
return sum;
}
如果要返回一个单对象, 就要注意, 如果是单表达式,第一种会报错, 要使用第二种方式。
// 这样写会出错
x => {foo:x} // 这和函数体{}有冲突
// 写成这种
x => {{foo:x}}
使用案例:
var sum = (x,y)=>{
console.log("箭头函数内部");
return x+y;
}
console.log("sum res:"+sum(5,6));
二、Promise对象(承诺)
js语言的执行环境是“单线程”。所谓单线程,就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务。
在实际的业务中,异步模式是非常重要的角色。我们可以有多种异步编程的方法,比如通过回调函数,但回调函数缺乏顺序性和可信任性。这个时候promise就很重要了。
1、Promise对象的两个特点
(1) 对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:
- pending: 初始状态,进行中。
- fulfilled: 已成功。
- rejected: 已失败。
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。
每一个异步任务返回一个promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成: f1().then(f2);
- 每个异步任务都将返回一个
then
对象。 - 每个
then
对象都有一个then
函数可以带两个参数,一个success
处理程序和error
处理程序。 then
函数中的成功或错误处理程序将仅在之后调用一次异步任务完成。
2、Promise的优缺点
优点:
- 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
- Promise 对象提供统一的接口,使得控制异步操作更加容易。
缺点:
- 无法取消 Promise,一旦新建它就会立即执行,无法中途取消。
- 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。
- 当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
2、基本用法
(1)Promise构造函数接受一个函数作为参数。该函数的两个参数分别是resolve和reject,它们是两个函数,由JavaScript引擎提供,不用自己部署。
- resolve函数的作用:将Promise对象的状态从“Pending未完成” 变为 "Resolved成功",在异步操作成功时调用,并将异步操作的结果作为参数传递出去;
- reject函数的作用:将Promise对象的状态从“Pending未完成” 变为 "Rejectd失败",在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去;
实例1:
var promise = new Promise(function(resolve,reject){
//释放资源,关闭窗口等操作
if(/*异步操作成功*/)
{
resolve('success');
}else{
reject('failed');
}
});
(2)Promise实例生成以后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数。then方法接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为Rejected时调用。其中第二个函数是可选的,可以不提供。这两个函数都接受Promise对象传出的值作为参数。
实例2:
function main() {
let promise =new Promise((resolve,reject)=>{
for(var i=0;i<3;i++)
{
console.log("i:"+i);
}
if(i==3)
{
resolve(i);
}else{
reject(i);
}
});
promise.then((value)=>{
console.log("success:"+value);
},()=>{
console.log("failed:"+value);
});
console.log("test end");
}
实例2测试结果:
Promise新建后就会立即执行。所以首先输出的是1~3。then方法指定的回调函数将在当前脚本所有同步任务执行完成后才会执行,所以“success:3”最后输出。
实例3:
//catch(failureCallback) 是 then(null, failureCallback) 的缩略形式。
//then() 函数会返回一个和原来不同的新的Promise2
var promise2 = promise.then(function(res){
console.log(res);
}).catch(err=>{
console.log(err);
})
3、链式调用
连续执行两个或者多个异步操作是一个常见的需求,在上一个操作执行成功之后,开始下一个的操作,并带着上一步操作所返回的结果。我们可以通过创造一个 Promise 链来实现这种需求。
new Promise((resolve, reject) => {
console.log('初始化');
resolve();
})
.then(() => {
throw new Error('有哪里不对了');
console.log('执行「这个」”');
})
.catch(() => {
console.log('执行「那个」');
})
.then(() => {
console.log('执行「这个」,无论前面发生了什么');
});
三、async和await关键字
案例一:
async function f1()
{
return "abc";
//相当于 return new Promise((resolve)=>{ resolve("abc")});
}
案例二:
function f1()
{
return new Promise((resolve,reject)=>{
setTimeout(()=>{resolve('success')},2000)
});
}
async function f5()
{
var c = await f1();
console.log(c);
console.log('aaa');//等待f1执行完之后再执行
}
f5();
案例三:
async function f1()
{
return Promise.reject('sss');
}
async function f5()
{
try{
var c = await f1();
}catch(e){
console.log(e);
}
console.log(c);//上面reject后,这行及以后的语句不会执行
console.log('aaa');
}
f5();
案例四:await的返回值
如果await得到不是一个promise对象,那么就不会等待这个异步操作。
如果是一个promise对象,await就会等待promise对象的resolve,得到传入resolve的参数,作为返回值。