Promise与异步编程
Promise是异步编程得一种解决方案,比传统的得方式(回调函数)更加合理强大
Promis对象特点
1、对象状态不受外界影响
2、一旦状态改变就不会改变,任何时候都可以得到结果
Promise对象缺点
1、无法中途取消
2、在pending状态出现错误时,如果没有设置回调,在promise的外部无法得知此错误。
例子分析
console.log("a");
setTimeout(() => console.log("b"));
let p = new Promise((resolve,reject)=>{
resolve();
console.log("c");
}).then(()=>{
console.log("d");
});
console.log("e");
以上代码的输出顺序为:
代码分析:c紧接着a输出是因为输出c的语句是一个同步任务,bd的输出顺序为先d后b,说明这两个是异步任务。
宏任务与微任务
1、宏任务和微任务是两个队列。
微任务的队列一般执行耗时少的任务,宏任务一般执行耗时长的任务。在宏任务中可能会包含微任务。
2、在入队时,先入队宏任务,再入队微任务。
3、在出队时,先出队微任务,再出队宏任务。也就是,所有微任务出队完成后,宏任务才会出队。
Promise基本用法
1、es6规定,promise对象是一个构造函数用来生成promise实例
2、promise构造函数有resolve和reject两个参数,这是两个函数,Promise实例对象生成以后可以用then方法指定resolve和rejected状态的回调函数。
3、resolve作用:从pendng状态转换成resolve,在异步操作成功时,将结果作为参数传递出去。
4、reject作用:将状态从”未完成“编程”失败“。
用法示例
function timeout(ms){
return new Promise((resolve,reject)=>{
setTimeout(resolve,ms,'done');
});
}
timeout(5000).then((value)=>{
console.log(value);
});
console.log('this going on...');
}
以上代码运行结果为:
代码分析:主要用setTimeout()模拟,setTimeout(resolve,ms,‘done’);中,ms的调用是同步的,resolve的调用是异步的。代码5s之后才会调用resolve。
示例2
let p1= new Promise((res,req)=>{
console.log("hello");//这是一条同步语句
});
p1.then(()=>{
console.log("promise then");
});
console.log("code end");//这是 一条同步语句
代码分析:同步任务代码比异步代码先执行,此时的异步代码并没有入队,因而没有输出。
代码修改之后,输出如下:
let p1= new Promise((res,req)=>{
console.log("hello");//这也是一条同步语句
return res(); //————不建议把该语句放在代码中间,一般放在代码结尾
});
p1.then(()=>{
console.log("promise then");//异步语句
});
console.log("code end");//这是 一条同步语句
示例3
var p1=new Promise((resolve, reject)=>{
setTimeout(()=>reject(new Error('fail')), 3000);
});
var p2=new Promise((resolve, reject)=>{
setTimeout(()=>resolve(p1), 1000);
});
p2.then(result=>console.log(result))
.catch(error=>console.log(error));
该函数的输出结果如图所示。一般,不要在then方法中定义rejected状态的回调函数,而应该总是使用catch方法。
链式调用
Promise实例可以链式的then( )调用,并且可以一直调用下去。
错误传递
setTimeout和setInterval两个函数都可以接受一个回调函数在某个未来的时间点上执行,属于异步执行。