引言
在Javasc里面,所有的代码都是单线程执行的,所以导致JS中所有的事件都必须异步执行。比如setTimeout(callback,1000),异步执行一般是通过调用回调函数来实现,用的最多的ajax
request.onreadystatechange = function () {
    if (request.readyState === 4) {
        if (request.status === 200) {
            return success(request.responseText);
        } else {
            return fail(request.status);
        }
    }
}
把回调函数写在ajax里面,既不好看也不利于代码复用,所以Promise出来了
正文
Promise的语法
new Promise(function(resolve,reject){   //实例一个promise对象
      if(true){
        resolve("aaaa");  //promise的第一个参数,表示成功,接下来会执行then()
      }else{
        reject("bbbbb");  //同上,表示失败,接下来会执行catch()
      }
  })      //执行函数
.then(function(result){console.log(result)}) //resolve调用then()  输出"aaaa"
.catch(function(reason){console.log(reason)}) //reject调用catch() 输出"bbbbb"
Promise的特点
- 对象的状态不受外界干扰,也就是说一旦执行了就停不下来,而且执行结果也无法更改。promise有三种状态:pending(执行中),fulfilled(成功),rejected(失败)。这三个状态其实就是个概念,没甚用。
- 状态改变后就不会再变,也就是说函数执行完好久好久了,给它加个回调函数它仍然能立即返回结果。
Promise连环使用
new Promise().then().then().then().catch()
上面的代码依次指定了三个回调函数,第一then()执行完(必须包含return语句),将返回结果作为参数传给下一个then()
then()有两个参数,then(function(){},function(){})第一个是resolve的回调函数,第二个可选参数是reject的回调函数,相当于catch()。不过一般不会这样用,因为Promise对象的错误有冒泡的特性,会一直传递,上面例子的catch()语句可以捕获三个then()里面的错误,当捕获到错误时,后面的then()就会跳过,不再执行。
Promise的执行顺序
new Promise(function(resolve,reject){
    console.log(1)
    setTimeout(function(){
       console.log(2)
  },101)
  resolve()
}).then(function(res){
    console.log(3)
});
console.log(4)
setTimeout(function(){
    console.log(5)
},100)
结果是 1 4 3 5 2
粗浅分析:假如上面的代码是一个线程的,那么
setTimeout()其实是在下一个线程上执行,new Promise()的参数函数时立即执行的,Promise的then()这是这当前线程的最末尾执行,所以setTimeout()时最晚执行的,先输出5,是因为一个是100ms,一个是101ms
finally语句
new Promise().then().catch().finally()
跟try..catch语句一样,finally不管怎样都要执行的
Promise.all()
Promise.all([p1,p2,p3]).then()
参数是Promise实例的数组,当P1,P2,P3都执行完的时候再执行then()
var p1 = new Promise(function(resolve,reject){
    resolve(1)
})
var p2 = new Promise(function(resolve,reject){
    resolve(2)
})
Promise.all([p1,p2]).then(function(res){
    console.log(res)   //[1,2]
})
then()接收的值是所有实例对象返回值组成的数组
Proomise.race()
Promise.race([p1,p2,p3]).then()
跟Promise.all()类似,不同的是race哪个实例先执行完立马调用then()
引出async
Promise有一种情况,ajax请求接口返回id,用返回的id去ajax请求另外一个接口,用Promise实现如下:
var p1 = new Promise(function(resolve,reject){
    setTimeout(function(){resolve(1)},100);
})
p1.then(function(id){
    new Promise(function(resolve,reject){
    setTimeout(function(){resolve(id+1)},100);
}).then(function(name){
    console.log(name)
})
})
这仅仅是一次嵌套而且代码简单可读性就很差,如果多次嵌套那绝对看眼花,所以引入async函数,用async重写
(async function(){
    let id = await new Promise(resolve => setTimeout(()=>resolve(1),100))
    let name  = await new Promise(resolve => setTimeout(()=>resolve(id+1),100))
    console.log(name)
})()
从上至下,一目了然
异步函数
存在的意义:提高promise的可读性
语法:
async function mytest(){
    try{
        const returnValue = await promise;
    }
    catch(rejectedValue){
        //
    }
}
如果在函数开头使用关键字async,就可以在函数里面使用await,当await
某个promise时,函数会暂停执行,直到该promise产生结果,并且暂停不会阻塞
主线程。
示例
function logFetch() {
    return fetch(url).then(response => responset.text())
    .then(text => {
        console.log(text);
    }).catch(err => {
        console.log(err);
    })
}
使用异步函数重写
async function logFetch() {
    try{
        var response = awit fetch(url);
        console.log(response.text());
    }
    catch(err){
        console.log(err);
    }
}