async/await

async的作用:

  • This is one of the traits of async functions — their return values are guaranteed to be converted to promises.
  • So the async keyword is added to functions to tell them to return a promise rather than directly returning the value.
  • an async keyword turns a function into a promise.
  • Return value:A Promise which will be resolved with the value returned by the async function, or rejected with an exception thrown from, or uncaught within, the async function.
  • Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.
  • The body of an async function can be thought of as being split by zero or more await expressions. Top-level code, up to and including the first await expression (if there is one), is run synchronously. In this way, an async function without an await expression will run synchronously. If there is an await expression inside the function body, however, the async function will always complete asynchronously.

await的作用:

  • await can be put in front of any async promise-based function to pause your code on that line until the promise fulfills, then return the resulting value.
  • The await keyword causes the JavaScript runtime to pause your code on this line, not allowing further code to execute in the meantime until the async function call has returned its result.
  • The await keyword blocks execution of all the code that follows it until the promise fulfills, exactly as it would with a synchronous operation. It does allow other tasks to continue to run in the meantime, but the awaited code is blocked. 
  • Await expressions make promise-returning functions behave as though they're synchronous by suspending execution until the returned promise is fulfilled or rejected. 
  • The resolved value of the promise is treated as the return value of the await expression.
  • Code after each await expression can be thought of as existing in a .then callback. In this way a promise chain is progressively constructed with each reentrant step through the function. The return value forms the final link in the chain.
  • Returns the fulfilled value of the promise, or the value itself if it's not a Promise.
  • The await expression causes async function execution to pause until a Promise is settled (that is, fulfilled or rejected), and to resume execution of the async function after fulfillment.
  • When resumed, the value of the await expression is that of the fulfilled Promise.
  • If the Promise is rejected, the await expression throws the rejected value.
  • If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise.
  • An await splits execution flow, allowing the caller of the async function to resume execution. 
  • After the await defers the continuation of the async function, execution of subsequent statements ensues.
  • If this await is the last expression executed by its function, execution continues by returning to the function's caller a pending Promise for completion of the await's function and resuming execution of that caller.
  • If a Promise is passed to an await expression, it waits for the Promise to be fulfilled and returns the fulfilled value.
  • If the value is not a Promise, it converts the value to a resolved Promise, and waits for it.
  • If the Promise is rejected, the rejected value is thrown.

Checking equality with Promise.resolve vs async return

注意func1与func5的区别。func5是异步非阻塞执行立即返回Promise { <pending> }。

注意func3的结果。

const p = new Promise((resolve, reject) => {
	resolve('value');
})

async function func1() {
	return 'value';
}
//...is similar to:
function func2() {
	return Promise.resolve('value');
}

async function func3() {
	return p;
}
//...is similar to:
function func4() {
	return Promise.resolve(p);
}

/*
If this await is the last expression executed by its function, execution continues by returning to the 
function's caller a pending Promise for completion of the await's function and resuming execution of 
that caller.
*/
async function func5() {
	await 'value';
}
//...is equivalent to:
function func6() {
    // The then handlers are called asynchronously.
	return Promise.resolve('value').then(() => undefined);
}

console.log(func1());	// Promise { 'value' }
console.log(func2());	// Promise { 'value' }
console.log(func3());	// Promise { <pending> }
console.log(func4());	// Promise { 'value' }
console.log(func5());	// Promise { <pending> }
console.log(func6());	// Promise { <pending> }

Promise.resolve('value');作为最后一条语句时函数的返回值

注意test3与test4、test3与test7(重点)的区别。

/* test1 */
function getVaule() {
	Promise.resolve('value');
}
console.log(getVaule());    // undefined


/* test2 */
function getVaule() {
	new Promise(resolve => {
		setTimeout(() => {
			resolve('value');
		}, 1000);
	});
}
console.log(getVaule());	// undefined


/* test3 */
function getVaule() {
	return Promise.resolve('value');
}
console.log(getVaule());	// Promise { 'value' }


/* test4 */
function getVaule() {
	return new Promise(resolve => {
		setTimeout(() => {
			resolve('value');
		}, 1000);
	});
}
console.log(getVaule());	// Promise { <pending> }


/* test5 */
async function getVaule() {
	Promise.resolve('value');
}
console.log(getVaule());	// Promise { undefined }


/* test6 */
async function getVaule() {
	new Promise(resolve => {
		setTimeout(() => {
			resolve('value');
		}, 1000);
	});
}
console.log(getVaule());	// Promise { undefined }


/* test7 */
async function getVaule() {
	return Promise.resolve('value');
}
console.log(getVaule());	// Promise { <pending> }


/* test8 */
async function getVaule() {
	return new Promise(resolve => {
		setTimeout(() => {
			resolve('value');
		}, 1000);
	});
}
console.log(getVaule());	// Promise { <pending> }


/* test9 */
/*
If this await is the last expression executed by its function, execution continues by returning to the 
function's caller a pending Promise for completion of the await's function and resuming execution of 
that caller.
*/
async function getVaule() {
	await Promise.resolve('value');
}
console.log(getVaule());	// Promise { <pending> }


/* test10 */
/*
If this await is the last expression executed by its function, execution continues by returning to the 
function's caller a pending Promise for completion of the await's function and resuming execution of 
that caller.
*/
async function getVaule() {
	await new Promise(resolve => {
		setTimeout(() => {
			resolve('value');
		}, 1000);
	});
}
console.log(getVaule());	// Promise { <pending> }


/* test11 */
async function getVaule() {
	return await Promise.resolve('value');
}
console.log(getVaule());	// Promise { <pending> }


/* test12 */
async function getVaule() {
	return await new Promise(resolve => {
		setTimeout(() => {
			resolve('value');
		}, 1000);
	});
}
console.log(getVaule());	// Promise { <pending> }

If an error is thrown in the Promise constructor, the promise is rejected.

let p = new Promise((resolve, reject) => {
    throw new Error('error');
});

p.catch(e => {
    console.error(e.message);    // error
});

If a handler function throws an error, the promise returned by then/catch gets rejected with the thrown error as its value.

Promise.resolve()
.then(() => {
    // Makes .then() return a rejected promise
    throw new Error('error');
})
.catch(e => {
    console.error(e.message);    // error
})

func():func内部同步阻塞执行await promise-based-API语句和其他常规语句,异步非阻塞执行promise-based-API和setTimeout/setInterval,func本身异步非阻塞执行。

await func():func内部同步阻塞执行await promise-based-API语句和其他常规语句,异步非阻塞执行promise-based-API和setTimeout/setInterval,func本身同步阻塞执行。

try/catch与throw Error的组合测试输出:

test4、test8表明:Async function will return a Promise which will be rejected with an exception thrown from, or uncaught within, the async function.

test4中:

  1. throw抛出Error使得async func返回Promise { <rejected> Error: error };
  2. 未处理Promise { <rejected> Error: error }导致UnhandledPromiseRejectionWarning;
  3. catch未能捕获throw抛出的Error。

test8中:

  1. throw抛出Error使得async func返回Promise { <rejected> Error: error };
  2. await func()等效于await Promise { <rejected> Error: error },根据"If the Promise is rejected, the await expression throws the rejected value.",将Error抛出;
  3. catch捕获Error并打印error。
/* test1 */
function func() {
	try {
		throw new Error('error');
	} catch(e) {
		console.error(e.message);	// error
	}
}

func();


/* test2 */
function func() {
	throw new Error('error');
}

try {
	func();
} catch(e) {
	console.error(e.message);	// error
}


/* test3 */
async function func() {
	try {
		throw new Error('error');
	} catch(e) {
		console.error(e.message);	// error
	}
}

func();


/* test4 */
async function func() {
	throw new Error('error');
}

try {
	func();    // UnhandledPromiseRejectionWarning: Error: error
} catch(e) {
	console.error(e.message);
}


/* test5 */
function func() {
	try {
		throw new Error('error');
	} catch(e) {
		console.error(e.message);	// error
	}
}

(async function() {
	await func();	
})();


/* test6 */
function func() {
	throw new Error('error');
}

(async function() {
	try {
		await func();
	} catch(e) {
		console.error(e.message);	// error
	}
})();


/* test7 */
async function func() {
	try {
		throw new Error('error');
	} catch(e) {
		console.error(e.message);	// error
	}
}

(async function() {
	await func();	
})();


/* test8 */
async function func() {
	throw new Error('error');
}

(async function() {
	try {
		await func();
	} catch(e) {
		console.error(e.message);	// error
	}
})();

try/catch与产生promise rejection的组合测试输出: 

test1、test2、test5表明:Synchronous try...catch won't work in async code.

test3、test6、test7、test8表明:

  • If the Promise is rejected, the await expression throws the rejected value.
  • Use of async and await enables the use of synchronous try / catch blocks around asynchronous code.

根据test4'可知,在test4中,语句func()前没有await故func异步非阻塞执行立即返回Promise { <pending> },随后生成未处理的Promise { <rejected> 'reason' },故抛出UnhandledPromiseRejectionWarning。

/* test1 */
function func() {
	try {
		Promise.reject('reason');    // UnhandledPromiseRejectionWarning: reason
	} catch(e) {
		console.error(e);
	}
}

func();


/* test2 */
function func() {
	return Promise.reject('reason');	// UnhandledPromiseRejectionWarning: reason
}

try {
	func();
} catch(e) {
	console.error(e);
}


/* test3 */
async function func() {
	try {
		await Promise.reject('reason');
	} catch(e) {
		console.error(e);	// reason
	}
}

func();


/* test4 */
async function func() {
    await Promise.reject('reason');
}

try {
	func();
} catch(e) {
	console.error(e);
}    // UnhandledPromiseRejectionWarning: reason


/* test4' */
async function func() {
    await Promise.reject('reason');
}

try {
	console.log(func());
	console.log('11111');
} catch(e) {
	console.error(e);
}
console.log('22222');
/*
output:
Promise { <pending> }
11111
22222
UnhandledPromiseRejectionWarning: reason
*/


/* test5 */
function func() {
	try {
		Promise.reject('reason');	// UnhandledPromiseRejectionWarning: reason
	} catch(e) {
		console.error(e);
	}
}

(async function() {
	await func();	
})();


/* test6 */
function func() {
	return Promise.reject('reason');
}

(async function() {
	try {
		await func();
	} catch(e) {
		console.error(e);	// reason
	}
})();


/* test7 */
async function func() {
	try {
		await Promise.reject('reason');
	} catch(e) {
		console.error(e);	// reason
	}
}

(async function() {
	await func();	
})();


/* test8 */
async function func() {
	await Promise.reject('reason');
}

(async function() {
	try {
		await func();
	} catch(e) {
		console.error(e);	// reason
	}
})();

try/catch与throw promise rejection的组合测试输出: 

throw await Promise.reject('reason')等效于await Promise.reject('reason')等效于throw 'reason'(测试“.then/.catch与throw promise rejection的组合测试输出:test3”的添加与删除throw两种情况,可验证在尾部链接.then/.catch的情况下,两者不等效)。

根据test4'可知,在test4中,语句func();前没有await故func异步非阻塞执行立即返回Promise { <pending> },随后生成未处理的Promise { <rejected> 'reason' },故抛出UnhandledPromiseRejectionWarning。

test4''中,语句func();前没有await故func异步非阻塞执行立即返回Promise { <rejected> Promise { <rejected> 'reason' } }。

test6中,由于func并非async函数,throw抛出Promise.reject('reason')后func不会返回Promise { <rejected> Promise { <rejected> 'reason' } },而是直接被catch捕获。func()的值目前未知。注意与“try/catch与throw Error的组合测试输出”test8进行比较。

/* test1 */
function func() {
	try {
		throw Promise.reject('reason');
	} catch(e) {
		console.error(e);	// Promise { <rejected> 'reason' } 
	}						// UnhandledPromiseRejectionWarning: reason
}

func();


/* test2 */	
function func() {
    throw Promise.reject('reason');
}

try {
	func();
} catch(e) {
	console.error(e);	// Promise { <rejected> 'reason' }
}						// UnhandledPromiseRejectionWarning: reason


/* test3 */	
async function func() {
	try {
		throw await Promise.reject('reason');
	} catch(e) {
		console.error(e);	// reason
	}
}

func();


/* test4 */	
async function func() {
	throw await Promise.reject('reason');
}

try {
	func();
} catch(e) {
	console.error(e);
}    // UnhandledPromiseRejectionWarning: reason


/* test4' */	
async function func() {
	throw await Promise.reject('reason');
}

try {
	console.log(func());
    console.log(11111);
} catch(e) {
	console.error(e);
}
console.log(22222);
/*
output:
Promise { <pending> }
11111
22222
UnhandledPromiseRejectionWarning: reason
*/


/* test4'' */	
async function func() {
	throw Promise.reject('reason');
}

try {
	console.log(func());
	console.log(11111);
} catch(e) {
	console.error(e);
}
console.log(22222);
/*
output:
Promise { <rejected> Promise { <rejected> 'reason' } }
11111
22222
UnhandledPromiseRejectionWarning: reason
UnhandledPromiseRejectionWarning: #<Promise>
*/


/* test5 */
function func() {
	try {
		throw Promise.reject('reason');
	} catch(e) {
		console.error(e);	// Promise { <rejected> 'reason' }
	}						// UnhandledPromiseRejectionWarning: reason
}

(async function() {
	await func();
})();


/* test6 */
function func() {
    throw Promise.reject('reason');
}

(async function() {
	try {
		await func();
	} catch(e) {
		console.error(e);	// Promise { <rejected> 'reason' }
	}						// UnhandledPromiseRejectionWarning: reason
})();


/* test7 */
async function func() {
	try {
		throw await Promise.reject('reason');
	} catch(e) {
		console.error(e);	// reason
	}
}

(async function() {
	await func();
})();


/* test8 */
async function func() {
    throw await Promise.reject('reason');
}

(async function() {
	try {
		await func();
	} catch(e) {
		console.error(e);	// reason
	}
})();

.then/.catch与产生promise rejection的组合测试输出: 

/* test1 */
function func() {
	Promise.reject('reason')
	.catch(console.error);	// reason
}

func();


/* test2 */
function func() {
	return Promise.reject('reason');
}

func()
.catch(console.error);	// reason


/* test3 */
async function func() {
	await Promise.reject('reason')
	.catch(console.error);	// reason
}

func();


/* test4 */
async function func() {
	await Promise.reject('reason');
}

func()
.catch(console.error);    // reason


/* test5 */
function func() {
	Promise.reject('reason')
	.catch(console.error);	// reason
}

(async function() {
	await func();	
})();


/* test6 */
function func() {
	return Promise.reject('reason');
}

(async function() {
	await func()
	.catch(console.error);	// reason
})();


/* test7 */
async function func() {
	await Promise.reject('reason')
	.catch(console.error);	// reason
}

(async function() {
	await func();	
})();


/* test8 */
async function func() {
	await Promise.reject('reason');
}

(async function() {
	await func()
	.catch(console.error);	// reason
})();

.then/.catch与throw promise rejection的组合测试输出:

  1. 根据test3'可知,在test3中,语句func();前没有await故func异步非阻塞执行立即返回Promise { <pending> };
  2. 随后Promise { <pending> }生成Promise { <rejected> 'reason' };
  3. Promise { <rejected> 'reason' }调用.catch(console.error)打印reason;
  4. await Promise.reject('reason').catch(console.error);返回值为undefined,throw将该undefined从async函数中抛出,使得async函数返回Promise { <rejected> undefined },故产生UnhandledPromiseRejectionWarning。

test5、test6暂不要求理解。

/* test1 */
function func() {
	throw Promise.reject('reason')
	.catch(console.error);
}

func();
/*
语法错误
        throw Promise.reject('reason')
        ^
[object Promise]
*/


/* test2 */
function func() {
	throw Promise.reject('reason');
}

func()
.catch(console.error);
/*
语法错误
		throw Promise.reject('reason');
		^
[object Promise]
*/


/* test3 */
async function func() {
	throw await Promise.reject('reason')
	.catch(console.error);	// reason UnhandledPromiseRejectionWarning: undefined
}

func();


/* test3' */
async function func() {
	throw await Promise.reject('reason')
	.catch(console.error);	// reason UnhandledPromiseRejectionWarning: undefined
}

console.log(func());
/*
output:
Promise { <pending> }
reason
UnhandledPromiseRejectionWarning: undefined
*/


/* test4 */
async function func() {
	throw await Promise.reject('reason');
}

func()
.catch(console.error);	// reason


/* test5 */
function func() {
	throw Promise.reject('reason')
	.catch(console.error);	// reason
}

(async function() {
	await func();    // UnhandledPromiseRejectionWarning: #<Promise>
})();


/* test6 */
function func() {
	throw Promise.reject('reason');	// UnhandledPromiseRejectionWarning: reason
}

(async function() {
	await func()
	.catch(console.error);    // UnhandledPromiseRejectionWarning: #<Promise>
})();


/* test7 */
async function func() {
	throw await Promise.reject('reason')
	.catch(console.error);	// reason
}

(async function() {
	await func();    // UnhandledPromiseRejectionWarning: undefined
})();


/* test8 */
async function func() {
	throw await Promise.reject('reason');
}

(async function() {
	await func()
	.catch(console.error);	// reason
})();

.then/.catch与throw Error的组合测试输出: 

test4、test8表明: Async function will return a Promise which will be rejected with an exception thrown from, or uncaught within, the async function.

/* test1 */
function func() {
	throw new Error('error')
	.catch(e => console.error(e.message));    // TypeError
}

func();


/* test2 */
function func() {
	throw new Error('error');	// UnhandledError
}

func()
.catch(e => console.error(e.message));


/* test3 */
async function func() {
	throw await new Error('error')
	.catch(e => console.error(e.message));	// TypeError
}

func();


/* test4 */
async function func() {
	throw await new Error('error');
}

func()
.catch(e => console.error(e.message));	// error


/* test5 */
function func() {
	throw new Error('error')
	.catch(e => console.error(e.message));	// TypeError
}

(async function() {
	await func();	
})();


/* test6 */
function func() {
	throw new Error('error');	// UnhandledError
}

(async function() {
	await func()
	.catch(e => console.error(e.message));
})();


/* test7 */
async function func() {
	throw await new Error('error')
	.catch(e => console.error(e.message));	// TypeError
}

(async function() {
	await func();	
})();


/* test8 */
async function func() {
	throw await new Error('error');
}

(async function() {
	await func()
	.catch(e => console.error(e.message));	// error
})();

(async () =>
{
	console.log(11111);
	await new Promise((resolve) =>
	{
		console.log(22222);
		setTimeout(() =>
		{
			console.log(33333);
			resolve();
			console.log(44444);
		}, 1000);
	});
	console.log(55555);
})();
console.log(66666);
/*
11111
22222
66666
33333
44444
55555
*/

(async () =>
{
	console.log(11111);
	await new Promise((resolve) =>
	{
		console.log(22222);
		resolve();
		console.log(33333);
		
	});
	console.log(44444);
})();
console.log(55555);
/*
11111
22222
33333
55555
44444
*/

(async () =>
{
	console.log(11111);
	await new Promise((resolve) =>
	{
		console.log(22222);	
	});
	console.log(33333);
	
})();
console.log(44444);
/*
11111
22222
44444
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值