Promise / Async Await

275 阅读2分钟

promise解决什么问题?

简单版回答:回调地狱
啰嗦版回答:在编程中我们会涉及到异步操作(如请求/io操作等)
由于我们不能直接拿到结果

function request() {
    let response
    setTimeout(() => {
        response = '假装是个响应结果'
    }, 3000)
    return response
}
console.log(request())//输出undefined,因为是异步的直接拿不到

所以在es5的时候我们会通过回调函数的方式拿到结果

function request(callback1) {
    setTimeout(() => {
        var response = '假装是个响应结果'
        callback1(response)
    }, 1000)
}
function callback1(response) {
    console.log(response)
}
request(callback1)

你会想这么写不是挺好的吗?其实如果编码能力强,到也不太可能回调地狱,大部分是人的问题所以会出现下面这样的代码(不用理解,看看就行,反正就是一层套一层)

//简答来说:这种代码是因为需要拿到一个结果后去判断它成功或失败后才能进行下一步操作,一层套一层,就会显得很臃肿,很乱
fs.readdir(source, function (err, files) {
    if (err) {
        console.log('Error finding files: ' + err)
    }
    else {
        files.forEach(function (filename, fileIndex) {
            console.log(filename)
            gm(source + filename).size(function (err, values) {
                if (err) {
                    console.log('Error identifying file size: ' + err)
                } else {
                    console.log(filename + ' : ' + values)
                    aspect = (values.width / values.height)
                    widths.forEach(function (width, widthIndex) {
                        height = Math.round(width / aspect)
                        console.log('resizing ' + filename + 'to ' + height + 'x' + height)
                        this.resize(width, height).write(dest + 'w' + width + '_' + filename, function (err) {
                            if (err) console.log('Error writing file: ' + err)
                        })
                    }.bind(this))
                }
            })
        }
        )
    }
})

使用promise,上面这种的代码结构就可以变的很简单,更像同步代码

//这是封装
const request = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const number = Math.floor(Math.random() * 10)
            if (number > 5) {
                resolve(number)
            } else {
                reject('小于5的我都不要')
            }
        })
    })
}
//这是调用后的操作,可以一直then 只要你愿意,也就是说无论你有多少层逻辑,你的代码最差也就长这样,当然 你使用async await 语法 会更香同步代码
request()
    .then((number) => {
        console.log('1')
        return number
    }).then((number) => {
        console.log('2')
        return number
    }).then(
        number => console.log(`成功拿到数字:${number}`),//成功的回调
        res => console.log(`失败的回调:${res}`)//失败的回调
    )


promise的优点是什么?(对比其他技术 -pros)

  1. 减少缩进(代码看起来更加整洁,更像同步代码)

Promise API

Promise.resolve

//制造一个成功或者失败的promise
function shake() {
    return Promise.resolve(new Promise((resolve, reject) => {
        return reject('fail')
    }))
}
shake().then(res => console.log(res), res => console.log(res))

Promise.reject

Promise.reject('失败')//制造一个失败的promise

Promise.all
一般用的少,因为只返回第一个失败

//接受一个promise数组,全部成功返回resolve数组,一个失败立即返回失败
Promise.all([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]).then(resultList => console.log(resultList))

解决串行办法

Promise.allSetled
兼容性不是很好

const taskList = [Promise.resolve(1), Promise.reject(2), Promise.resolve(2), Promise.resolve(3)]
function successfulAndFailed(resultList) {
    console.log(`成功和失败的结果都在这里`)
    console.log(resultList)
}
Promise.allSettled(taskList).then(successfulAndFailed)