JavaScript必学之promise异步编程理解使用

概述

为了避免线程同步问题,js采用了单线程模式,但因为单线程模式的耗时任务阻塞问题,所以将js的执行模式分为同步模式和异步模式。而回调函数可以说是js所有异步模式的根基,直接使用传统的回调方式去完成复杂的异步编程,就无法避免大量回调函数嵌套(回调地狱),所以CommonJS社区先提出了promise的规范,最后在es2015标准化。

实际上promise就是一个对象,用来表示一个异步任务结束后是成功还是失败,就像他的中文一样,是一个承诺,等待时是Pending,承诺成功(Fulfilled)会调用onFilfilled函数,承诺失败(Rejected)后调用onRejected函数。

Pending要么变为Fulfilled,要么变为Rejected,并且一经改变就会被确定下来

其实是Promise对象内部有个status属性刚开始的值是Pending,经过resolve或reject函数调用改变成Fulfilled或者Rejected了而已。

下面我们来看具体的代码

promise具体使用

1.promise基本使用

const promise = new Promise(function(resolve,reject){
    if(成功的条件){
        resolve(100)
    }
    else{
        reject(new Error('promise reject'))
    }
    
})
promise.then(function(value){
    console.log(value);
}  //  onFilfilled函数
,function(err){
console.log(err);
})  //  onRejected函数

通过 new Promise来创建一个promise实例。其中promise内部传入了两个函数resolve和reject作为执行器函数(执行器函数也就是 new Promise后面括号里的函数)的实参,.then中的第一个函数是承诺成功后的回调(onFilfilled),第二个是承诺失败后的回调(onRejected)。

我们通过调用resolve方法resolve(100)传入一个值100 表示承诺成功,状态变为Fulfilled,这个值会返回给.then方法中成功函数(onFilfilled)中的回调的参数value,反之我们通过调用reject方法reject(new Error('promise reject'))new一个Error错误 表示承诺失败,状态变为Rejected,这个错误会返回给.then方法中失败函数(onRejected)中的回调的参数err

 成功的输出值

 失败的输出值

2.先封装一个ajax的get请求(想了解的可以看)

function ajax(url) {
    return new Promise(function(resolve,reject){
        var xhr =new XMLHttpRequest()
        xhr.open('GET',url)
        // 转化为json对象
        xhr.responseType = 'json'
        // 请求完成过后执行
        xhr.onload =function(){
            if(this.status ==200){
                //返回响应对象
                resolve(this.response)
            }else{
                reject(new Error(this.statusText))
            }
        }
        xhr.send()
    })
}

(1)我们来调用下这个ajax请求(提前创建了本地服务器并在3007端口设置好了一个/api/user的接口)

ajax('http://127.0.0.1:3007/api/user').then(function(res){
    console.log('成功');
    console.log(res);
},function(err){
    console.log('失败')
    console.log(err)
})

这是返回的结果

 我们再次调用一个不存在的接口

ajax('http://127.0.0.1:3007/api/sss').then(function(res){
    console.log('成功');
    console.log(res);
},function(err){
    console.log('失败')
    console.log(err)
})

 返回了

 3.链式调用

ajax('http://127.0.0.1:3007/api/user')
.then(function(res){   // 每次.then都会返回一个新的promise对象,可以继续调用.then实现链式调用
    console.log('成功');
    console.log(res);
    return 100
    // return的值作为下次成功函数的实参res
}).then(function(res){
    console.log(res);
   // 没有返回值则是undefined
}).then(function(res){
    console.log(res);
}).then(function(res){
   throw new Error('错误')
    console.log(res);
})
 // 可以用.catch 作为失败函数的回调,不写则会一直传递下去
.catch(function(err){
    console.log('no');
    console.log(err);
})

我们来看控制台输出结果

其实.catch(fn)等同于.then(undefined,fn)

 4.promise的一些其他静态方法

(1)Promise.all()

可以将多个Promise对象封装成一个Promise对象

const request1 = ajax('/api/user.json')
const request2 = ajax('/api/login.json')

Promise.all([request1,request2]).then(value =>{
    console.log(value);
})

输出结果

1. 只有当request1和request2的状态为成功(fulfilled)时 Promise.all()的状态才会变为成功(fulfilled),并将request1和request2的返回值组成一个新的返回值数组,传递给.then中成功的回调函数

2.两者有一个状态为失败(rejected),则新的Promise的状态为失败(rejected)

(2)Promise.race()

const aaa = new Promise((resolve,reject)=>{
    setTimeout(()=>{resolve('我的状态是成功,我先改变')},200)
})
const eee = new Promise((resolve,reject)=>{
    setTimeout(()=>{reject(new Error('nonono'))},500)
})
Promise.race([request1,eee]).then(function(value){
    console.log(value);
}).catch(err =>{
    console.log(err);
})

输出结果

跟all类似,可以将多个Promise对象封装成一个Promise对象,但是ta的状态和返回值是根据多个Promise中率先发生状态改变的那个Promise的状态和值。

(3)Promise.resolve()与Promise.reject()

Promise.resolve(111) 等同与 new Promise((reslove,reject)=>{reslove(111)})

Promise.reject('错误') 等同与 new Promise((reslove,reject)=>{reject('错误')})

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值