Promise 主要解决 Java Script 中异步的场景. Promise 是个对象, 同 JavaScript 中其它对象没什么区别, 但同时它也是一个规范, 针对异步操作约定了统一的接口, 表示一个一步操作最终的结果, 以同步的方式来写代码, 执行的操作是异步的, 但是又保证程序的执行顺序是同步的. 这原本是JavaScript社区的一个规范的构想, 现在已经被加入到了 ES6 的语言标准中, Firefox 和 Chrome 等浏览器已经对它进行了实现.
2.1 同步与异步
JS 引擎是单线程的. 这意味着在任何环境中, 只有一段 JS 代码会被执行. 每个函数是一个不可分割的片段或者代码块. 当 JS 引擎开始执行一个函数(比如回调函数)时, 它就会把这个函数执行完, 只有执行完这段代码才会继续执行后面的代码. 这就是 JS 中的同步. Promise 对象的 then()方法就是同步处理每个Promise 对象. 异步是指在执行一段代码时, 这段代码依赖一些其他的操作或者数据, 这时就不用等待数据或者操作的返回, 直接执行下一段代码, 当有数据或操作返回时再去响应之前的代码, 从而提高代码执行的效率.
2.2 Promise 对象的状态
Promise 对象只有三种状态:
- Pending: 初始状态进行中
- Resolved(或 Fulfilled): 成功的操作.
- Rejected: 失败的操作
Var promise=new Promise(function (resolve,reject){
//...some code
If(/*异步操作*/){
Resolve(value);//状态从pending变为resolved
}
else{
Reject(error)};//状态从pending变为rejected
});
- Promise 对象的状态不受外界影响Promise 对象代表一个异步操作有三种状态: Pending(进行中)、Resolved(已完成, 又称 Fulfilled)和Rejected(已失败). 只有异步操作的结果, 可以决定当前是哪一种状态, 任何其他操作都无法改变这个状态.
- Promise 对象一旦状态改变, 就不会再变, 任何时候都可以得到这个结果. Promise 对象的状态改变, 只有两种可能: 从Pending 变为 Resolved 和从 Pending 变为 Rejected. 只要这两种情况发生, 状态就凝固了, 不会再变了, 会一直保持这个结果. 就算改变已经发生了, 再对Promise 对象添加回调函数, 也会立即得到这个结果.
2.3 Promise 的核心方法
Promise对象的核心部件是它的then方法, 它的作用是为 Promise 实例添加状态改变时的回调函数. then方法接受两个回调函数作为参数. 第一个回调函数是Promise 对象的状态变为 Resolved 时调用, 第二个回调函数是 Promise 对象的状态变为 Rejected 时调用. 其中, 第二个函数是可选的, 不一定要提供. 这两个函数都接受 Promise 对象传出的值作为参数.
Promise.then(function(value){
//resolved状态时调用
},function(error){
//rejected状态调用
})
Promise 对象另一个核心方法是它的 catch方法, 用于指定发生错误时的回 调 函 数 , 是 then(null, rejection)的别名. catch 方法可以捕捉 promise 实例中的异常还能捕获在它之前太狠方法中发生的异常, 所以在实际的使用中, 多用 catch 方法来取代 then(null, rejection)处理异常.
Promise.then(function(value){
//resolved状态时调用
}).catch(function(error){
//处理promise和前一个回调函数运行时发生的错误
Console.log(“发生错误”,error);
});
ECMAscript 6 原生提供了 Promise 对象。Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。Promise 对象有三种状态:pending,初始状态;fulfilled,操作成功完成状态;rejected,操作失败状态。只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这种状态。Promise 的出现解决了传统 Javascript 异步回调嵌套模式,大大提高了程序的可读性[2]。比如,通过下面代码获取当前日期的程序来模拟Javascript传统异步回调操作,具体代码如下:
function fun(callback) {var year = "2020";
//setTimeout( )是属于 window 的 method, 但我们都是略去window 这顶层物件名称,这是用来设定一个时间, 时间到了, 就会执行一个指定的 method。
setTimeout(function() {
var date = year + "-09";
setTimeout(function() {
var day=date+"-16";
setTimeout(function() {
callback(day);
}, 1000, day);
}, 1000, date);
}, 1000, year);
}
fun(function(data) {
console.log(data);
})
在上面的程序中,要获取年月日的信息,需要等待3秒钟才可以返回,代码嵌套层数较多,可读性较差,如果我们采用Promise 来改写,将会大大提高代码的可读性,具体代码如下:
function fyear() //获取年份{
var year=new Promise(function(reslove,reject){
setTimeout(function(){
reslove('2020');
},1000);
});
return year;
}
function fmonth(data) //获取月份{
var month=new Promise(function(reslove,reject){
setTimeout(function(){
reslove(data+"-09");
})
},1000);
return month;
}
function fday(data) //获取日期{
var day=new Promise(function(reslove,reject){
setTimeout(function(){
reslove(data+"-16");
},1000);
});
return day;
}
fyear().then(fmonth).then(fday).then(function(data){console.log(data);
})使用 Promise 来实现 Javascript 异步操作,对函数的功能划分更清晰,大大提高了程序的可读性。