Skip to content

一、Promise的三种状态

  • pending 进行中:不会触发then和catch
  • resolved 成功:触发then
  • rejected 失败:触发catch

二、Promise 加载图片

js
function loadImg(src) {
	const p = new Promise((resolve,reject) => {
		const img = document.createElement('img')
		img.onload = () => {
			resolve(img)
		}
		img.onerror = () => {
			const err = new Error(`图片加载失败 ${src}}`)
			reject(err)
		}
		img.src = src
	})
	return p
}
const url1 = 'http://www.wensoul.com/static/img/avatar.jpg'
const url2 = 'http://www.wensoul.com/static/img/7de5437.png'
loadImg(url1).then(img1 => {
    console.log(img1.width);
    return img1
}).then(img1 => {
    console.log(img1.height)
    return loadImg(url2)
}).then(img2 => {
    console.log(img2.width)
    return img2
}).then(img2 => {
    console.log(img2.height)
}).catch(ex	 => {
    console.error(ex)
})

三、Promise的then和catch状态的改变

  • then正常返回resolved,里面有报错返回rejected
  • catch正常返回resolved,里面有报错返回rejected

没有报错都是,resolved状态,执行then

1.代码示例:

js
const p1 = Promise.resolve().then(() => {
	return 100;
})
console.log('p1',p1)//resolved,触发后续的then回调
p1.then(() => {
	console.log('123')
})
const p2 = Promise.resolve().then(() => {
	throw new Error('then error')
})
console.log('p2',p2)//rejected,触发后续catch回调
p2.then(() => {
	console.log('345')//触发不了
}).catch(() => {
	console.log('err',err)
})
const p3 = Promise.reject('my error').catch(err => {
    console.log(err)
})
console.log('p3',p3)//resolved状态,触发then回调
p3.then(() => {
    console.log(100)
})

const p4 = Promise.reject('my error').catch(err => {
    throw new Error('catch err')
})
console.log('p4',p4)//rejected状态 触发catch回调

p4.then(() => {
    console.log(200)
}).catch(() => {
    console.log('some err')
})

2.面试题示例:

js
Promise.resolve().then(() => {
    console.log(1)//1
}).catch(() => {
    console.log(2)
}).then(() => {
    console.log(3)//3
})

// 第二题
Promise.resolve().then(() => {
    console.log(1)//1  
    throw new Error('error1')  //返回rejected状态,执行catch
}).catch(() => {
    console.log(2)//2  返回resolved状态,触发then回调
}).then(() => {
    console.log(3)//3
})

// 第三题
Promise.resolve().then(() => {
    console.log(1) //1
    throw new Error('error')
}).catch(() => {
    console.log(2) //2
}).catch(() => {
    console.log(3)
})

四、async和await 语法

async/await 同步语法,消除回调函数

代码示例:
js
function loadImg(src) {
    const p = new Promise((resolve, reject) => {
        const img = document.createElement('img');
        img.onload = () => {
            resolve(img)
        }
        img.onerror = () => {
            const err = new Error(`图片加载失败 ${src}`)
            reject(err)
        }
        img.src = src
    })
    return p
}
const url1 = 'http://www.wensoul.com/static/img/avatar.jpg'
const url2 = 'http://www.wensoul.com/static/img/7de5437.png';
async function loadImg1() {
    const img1 = await loadImg(src1)
    return img1
}

(async function() {
    const img1 = await loadImg(src1)
    console.log(img1.height,img1.width)
})()

五、async/await和Promise的关系

async/await是消灭异步回调的终极武器,但和Promise并不互斥,两者相辅相成。
执行async函数,返回的是Promise对象,await相当于Promise的成功回调then,try。。。catch可捕获异常,代替了Promise的失败回调catch

js
async function fn1() {
	return 100
}
const res1 = fn1();//执行async函数,返回的是Promise对象
console.log(res1)
res1.then(data => {
	console.log('data',data)//11
})

!(async function () {
	const p1 = Promise.resolve(300)
	const data = await p1 //await相当于Promise then
	console.log('data',data)
})()

!(async function () {
	const data1 = await 400;//await Promise.resolve(400)
	console.log('data1',data1)//400
})()

!(async function () {
	const data2 = await fn1() //fn1返回Promise对象
	console.log('data2',data2)
})()

//try 。。catch捕获异常,代替了promise的catch
!(async function () {
	const p4 = Promise.reject('err')
	try{
		const res = await p4
		console.log(res)
	}catch(ex){
		console.log('ex',ex)
	}
})()

!(async function () {
	const p4 = Promise.reject('err')
	const res = await p4 // 不会执行,使用try catch捕获异常
	console.log('res',res)
})

六、异步的本质

async/await是消灭异步回调的终极武器。js还是单线程,还得是有异步,还得是基于event loop。async/await只是一个语法糖。
示例:

js
async function async1() {
	console.log('async1 start')//2
	await async2()
	//await行下面所有内容,都可以看做是callback里面的内容,即异步
    //类似event loop,setTimeout(cb1)
    //setTimeout(function () {console.log('async1 end')})
    //Promise.resolve().then(() => {console.log('async1 end')})
	console.log('async1 end')//5
}
async function async2() {
	console.log('async2')//3
}
console.log('script start')//1
async1()//执行async1 立马执行函数体,打印async1 start
console.log('script end')//4

另一种形式

js
async function async1() {
	console.log('async1 start') // 2
	await async2()
	console.log('async1 end') // 5
	await async3()
	console.log('async1 end 2') // 7
}
async function async2() {
	console.log('async2') // 3
}
async function async3() {
	console.log('async3') // 6
}
console.log('script start') // 1
async1();
console.log('script end') // 4

Released under the MIT License.