ES6-Promise异步编程

本文探讨了回调地狱问题在JavaScript中的困扰,并介绍了如何通过Promise进行异步编程,实现代码的扁平化,降低耦合度。通过实例演示了Promise的使用和常见方法如`.then()`和`.catch()`,以及静态方法`Promise.resolve()`和`Promise.reject()`。

Callback Hell回调地狱

方法一层层的嵌套,就形成回调地狱,类似下面这种:

function ajax (url, callback) {
    // 1.创建XMLHttpRequest对象
    var xmlHttp
    if (window.XMLHttpRequest) {
        xmlHttp = new XMLHttpRequest()
    } else {    //兼容早期ie浏览器
        xmlHttp = new ActiveXObject('Microsoft.XMLHTTP')
    }

    // 2.发送请求
    xmlHttp.open('GET', url, true)
    xmlHttp.send()

    // 服务端响应
    xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readState === 4 && xmlHttp.status === 200) {
            var obj = JSON.parse(xmlHttp.responseText)
            callback(obj)
        }
    }
}

/* var url = '******'
ajax(url, res => {
    console.log(res)
}) */

// 回调地狱
ajax('../static/a.json', resA => {
    console.log(resA)
    ajax('../static/b.json', resB => {
        console.log(resB)
        ajax('../static/c.json', resC => {
            console.log(resC)
        })
    })
})

回调地狱这种代码耦合性高,不太好

Promise异步编程

Promise可以解决回调地狱的问题,将代码扁平化,将一层一层嵌套的模式变为同级关系

Promise用法如下:

eg:

var p = new Promise((resolve, reject) => {
    // 异步处理程序
}).then(res => {
    // 执行成功状态
}, err => {
    // 执行失败状态
})

参数规定这么写:(resolve, reject)
resolve- - -成功状态参数
reject- - -失败状态参数

可以不两个参数都写

使用 then() 函数进行异步结果处理,可以写两个函数,第一个是执行成功的处理函数,第二个是执行失败的处理函数,第二个可以省略不写

还可以用 catch() 函数进行失败捕获

Promise程序处理状态
  1. pending- - -进行中
  2. fulfilled- - -成功状态
  3. rejected- - - 失败状态

处理完之后就是成功或者失败状态,状态确定之后,不再改变
eg: resolve()模拟状态成功后,再用reject()尝试更改状态为失败,但是更改无效

image.png

Promise使用代码示例:

Promise处理上面的回调地狱问题:
普通写法1:

function ajax (url, successCallback, failCallback) {
    // 1.创建XMLHttpRequest对象
    var xmlHttp
    if (window.XMLHttpRequest) {
        xmlHttp = new XMLHttpRequest()
    } else {    //兼容早期ie浏览器
        xmlHttp = new ActiveXObject('Microsoft.XMLHTTP')
    }

    // 2.发送请求
    xmlHttp.open('GET', url, true)
    xmlHttp.send()

    // 服务端响应
    xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readState === 4 && xmlHttp.status === 200) {
            var obj = JSON.parse(xmlHttp.responseText)
            successCallback && successCallback(obj)
        } else if(xmlHttp.readState === 4 && xmlHttp.status === 404) {
            failCallback && failCallback(xmlHttp.statusText)
        }
    }
}


var p1 = new Promise((resolve, reject) => {
    ajax('../static/a.json', res => {
        console.log(res)
        resolve()
    })
}).then(res => {
    console.log('a成功')
    return new Promise((resolve, reject) => {
        ajax('../static/b.json', res => {
            console.log(res)
            resolve()
        })
    })
}).then(res => {
    console.log('b成功')
    return new Promise((resolve, reject) => {
        ajax('../static/c.json', res => {
            console.log(res)
            resolve()
        })
    })
}).then(res => {
    console.log('c成功')
})

可以将Promise封装成函数使用:
①使用then() 第二个函数捕获异常err

// then() 第二个函数捕获异常err
getPromise('../static/a.json').then(res => {
    console.log('a成功: ' + res)
    return getPromise('../static/b.json')
}, err => {
    console.log('失败'+ err)
    return getPromise('../static/b.json')
}).then(res => {
    console.log('b成功: ' + res)
    return getPromise('../static/c.json')
}).then(res => {
    console.log('c成功: ' + res)
})

②catch() 捕获异常

// catch() 捕获异常
getPromise('../static/a.json').then(res => {
    console.log('a成功: ' + res)
    return getPromise('../static/b.json')
}).then(res => {
    console.log('b成功: ' + res)
    return getPromise('../static/c.json')
}).then(res => {
    console.log('c成功: ' + res)
}).catch(err => {
    console.log(err)
})

Promise实例方法

new Promise((resolve, reject) => {、、、}).then(、、、).cathch(、、、)

.then() .catch() 是实例方法

Promise静态方法

  1. Promise.resolve()
  2. Promise.reject()
  3. Promise.all()
  4. Promise.race()

静态方法可以直接调用
eg:

let p1 = Promise.let flag = true('成功')
console.log(p1)
p1.then(res => {
    console.log(res)
})

let p2 = Promise.reject('失败')
p2.catch(err => {
    console.log(err)
})

打印结果:

image.png

Promise.resolve()/Promise.reject()使用示例

有时没有通过new得到一个Promise实例,但是也想使用.then() .catch()方法,可以使用Promise.resolve() 或者 Promise.reject() 得到一个 Promise 对象

eg:

function foo(flag) {
    if(flag) {
        return new Promise(resolve => {
            resolve('success')
        })
    } else {
        // return 'fail'
        return Promise.reject('fail')
    }
}

// let flag = true
let flag = false
foo(flag).then(res => {
    console.log(res)
}, err => {
    console.log(err)
})

Promise.all()/Promise.race()使用示例

Promise.all()/Promise.race()的括号里面需要放一个数组,数组中每个元素需为Promise对象

eg:

let p1 = new Promise((resolve, reject) => {
    // setTimeout模拟异步操作
    setTimeout(() => {
        console.log(1)
        resolve('1成功')
    }, 1000)
})

let p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log(2)
        resolve('2成功')
        // reject('2失败')
    }, 2000)
})

let p3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log(3)
        resolve('3成功')
    }, 3000)
})

Promise.all([p1, p2, p3]).then(res => {
    console.log(res)
}, err => {
    console.log(err)
})

all中的所有Promise示例都会被执行,全部执行成功后,会执行then()里面的res成功状态方法
只要有一个失败,就会执行失败状态方法

全部成功打印结果:

image.png

有失败的打印结果:

image.png

Promise.all()/Promise.race()应用场景举例:图片上传,图片加载

图片一般是一张一张的上传,当全部上传成功时,提示图片上传成功
Promise.all()应用于图片上传- - -
伪代码:

const imgArr = ['1.jpg', '2.jpg', '3.jpg']
let promiseArr = []
imgArr.forEach(item => {
    promiseArr.push(new Promise((resolve, reject) => {
        // 图片上传操作
        resolve()
    }))
})

Promise.all(promiseArr).then(res => {
    console.log('图片全部上传成功')
})

Promise.race()应用于图片上传- - -
要么加载成功,要么加载超时:

function getImg() {
    return new Promise((resolve, reject) => {
        let img = new Image()
        img.onload = function() {
            resolve(img)
        }
        img.src = 'xx.jpg'
        // img.src = 'https://www.baidu.com/img/flexible/logo/pc/result@2.png'
    })
}

function timeout() {
    return new Promise((_resolve, reject) => {
        setTimeout(() => {
            reject('图片请求超时')
        }, 2000)
    })
}

Promise.race([getImg(), timeout()]).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

加载超时:

image.png

加载成功:

image.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值