彻底搞懂Promise

1,434 阅读4分钟

promise的优势

项目开发中,经常会遇到顺序请求多个接口,下一个接口请求参数需要依赖上一个接口的返回值,我们会这样写:

one(function(result) {
  two(result, function(newResult) {
    three(newResult, function(finalResult) {
      console.log(finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

在项目功能复杂时,嵌套更多,更深,结构向右发展,十分不利于阅读以及后期的代码维护。 我们看下promise的写法:

one().then(()=>{
	return two()
}).then(()=>{
	return three()
}).catch(failureCallback)

或者

let p = new Promise((resolve, reject) => {
            console.log('000')
            resolve(2)
        });
setTimeout(() => {
  p.then(value => {
      console.log(value)
  }).catch(err => {
      console.log(err)
  })
}, 1000);

由此可以看出,promise优势:

  • 1 可以链式调用,解决回调地狱问题,可以统一处理异常(异常穿透)
  • 2 指定回调函数的方式更加灵活, 可以在结果返回之后再指定处理函数

promise执行相关

看下面示例执行后输出什么

let p = new Promise((resolve, reject) => {
            console.log('0')
            resolve(2)
        })
p.then(value => {
    console.log('1.1>>>', value)
    return '成功'
}, reason => {
    console.log('1.2>>>', reason)
}).then(value => {
    console.log('value>>>', value)
}, reason => {
    console.log('reason>>>', reason)
})

p.then(value => {
    console.log('2.1>>>', value)
    return Promise.reject('5')
}).catch(err => {
    console.log('2.2>>>', err)
}).then(value=>{
    console.log('catch 后>>>', value)
})

setTimeout(() => {
    p.then(value => {
        console.log('3.1>>>', value)
    }).catch(err => {
        console.log('3.2>>>', err)
    })
}, 0);
console.log('4')

// 打印结果:
0, 
4, 
1.1>>> 2,
2.1>>> 2,
value>>> 成功,
2.2>>> 5,
catch 后>>> undefined,
3.1>>> 2,
  • 1) promise 执行器里的内容是同步执行的,绑定的回调函数是异步任务
  • 2) 一个promise实例可以绑定多个回调函数,回调函数按序执行
  • 3) 回调函数执行后会返回一个新的promise对象,该对象与之前创建的promise实例是两个不同的实例
  • 4) 绑定多个回调函数时,若实例状态变为rejected、回调函数中抛出异常,被下一个回调函数处理后且没有中断promise时,后续绑定的回调函数仍会继续执行
  • 5) 上一个回调函数的返回值会作为一下个回调函数的参数传入

Promise 静态方法

  • Promise.all([a,b,c]) //[a,b,c] 当全部成功时,按序返回成功的值,若有一个失败,则返回第一个失败的值
  • Promise.any([a,b,c]) //[a,b,c] 一个成功就成功,并返回成功的值
  • Promise.race([a,b,c]) //[a,b,c] 任何一个成功或者失败,就执行,返回那个成功或者失败的值
  • Promise.allSettled([a,b,c]) //[a,b,c] 按序返回所有结果,不管成功失败
  • Promise.resolve(value) // 返回一个状态由给定value决定的Promise对象,若value是一个带有then方法的对象,则最终状态由then方法的返回结果决定,所以该方法不一定总是返回成功的状态
  • Promise.reject(reason) // 返回一个状态为失败的Promise对象,并将给定的失败信息传递给对应的处理方法
let a = Promise.resolve(1)
let b = Promise.resolve(2)
let c = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('失败')
    }, 1000);
})
let d = Promise.reject(4)
Promise.all([a, b, c]).then(values => {
    console.log('all-success', values)
}, reason => {
    console.log('all-error', reason)
})
// all-error 失败

Promise.all([a, b]).then(values => {
    console.log('all-success', values)
}, reason => {
    console.log('all-error', reason)
})
// [1, 2]

Promise.any([c, d, a, b]).then(values => {
    console.log('any-success', values)
}, reason => {
    console.log('any-error', reason)
})
// any-success 1

Promise.race([d, b, c, a]).then(values => {
    console.log('race-success', values)
}, reason => {
    console.log('race-error', reason)
})
// race-error 4

Promise.allSettled([a, b, c, d]).then(values => {
    console.log('allSettled-success', values)
})
// [
{status: "fulfilled", value: 1},
{status: "fulfilled", value: 2},
{status: "rejected", reason: "失败"},
{status: "rejected", reason: 4}
]

let e = {
    then: function (resolve, reject) {
        // resolve(66)
        reject(77)
    },
    'a': 1
}
Promise.resolve(e).then(value => {
    console.log('resolve-success', value)
}, reason => {
    console.log('resolve-err', reason)
})
// 打印: 77

Promise.reject(8).then().catch(reason => {
    console.log('reject', reason)
})
// 8

async await

  • async函数返回一个promise对象,该对象的结果由async函数执行的返回值决定
  • await
    • 必须写在async函数中,不可单独使用
    • 若右侧是一个promise对象,则await返回的是promise的成功的值,若promise失败,则会抛出异常,需要有处理异常的语句处理
    • 若右侧是其他值,则直接将此值作为await的返回值
// await 右侧返回一个失败的promise
function delay() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(222)
        }, 1000)
    })
}
async function f() {
    let a = await delay()
}
f().then(value => {
    console.log('value', value)
}, reason => {
    console.log('reject', reason)
})
//打印: reject 222

function delay1() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(111)
        }, 1000)
    })
}
async function f1() {
    let a = await delay1()
    console.log(a)
}
f1()
// 打印 111

function delay2() {
    return 333
}
async function f2() {
    let a = await delay2()
    console.log(a)
}
f2()
// 打印 333

以上便是最近深入了解promise后的一些总结,在遇到不了解的地方还是需要多查阅文档,从根本上解决问题。 下面贴一道测试题,欢迎评论区留下你的答案

setTimeout(() => {
    console.log(1)
    Promise.resolve().then(value => {
        console.log(2)
    })
}, 0);

new Promise((resolve, reject) => {
    console.log(3)
    resolve()
}).then(() => {
    console.log(5)
    new Promise((resolve, reject) => {
        console.log(6)
        resolve()
    }).then(() => {
        console.log(7)
    }).then(() => {
        console.log(8)
    })
}).then(() => {
    console.log(9)
})
new Promise((resolve, reject) => {
    console.log(10)
    resolve()
}).then(() => {
    console.log(11)
})
console.log(12)