async,async await
java web异步请求中,async什么意思
async 是 asynchronous 就是异步标签。spring3之后支持@Async注解的异步任务,和java web无关。java web中servlet3.0标准支持异步http请求处理。现在常用的web mvc框架中个Spring MVC 3.2 M1 引入支持servlet3.0。
以下是来自 Spring 官方博客的消息:
Spring MVC 3.2 M1 将引入对异步请求处理的支持,基于 Servlet 3.0 规范。尽管该版本还没发布,你可以在这里看到包含的改进。
简单预览一下:
一个控制器方法可通过返回 Callable 来完成异步处理:
@RequestMapping(method=RequestMethod.POST)
public CallableString processUpload(final MultipartFile file) {
return new CallableString() {
public Object call() throws Exception {
// ...
return "someView";
}
};
}
或者控制器方法返回 DeferredResult (new in Spring 3.2 M1) 来完成处理
@RequestMapping("/quotes")
@ResponseBody
public DeferredResult quotes() {
DeferredResult deferredResult = new DeferredResult();
// Add deferredResult to a Queue or a Map...
return deferredResult;
}
// In some other thread..
// Set the return value on the deferredResult
deferredResult.set(data);
async里a是哪个单词
a代表的不是单独的单词。这是一个整体的单词。
async
英 [?'z??k] 美 [?'z??k]
adj. 异步的
async函数的基本用法
1. async函数的基本形式
//函数声明asyncfunction foo() {}//函数表达式const foo = asyncfunction () {};//对象的方法let obj = { async foo() {} };
obj.foo().then(...)//Class 的方法class Storage {
constructor() {
? ? this.cachePromise = caches.open('avatars');
}
async getAvatar(name) {
? ? const cache = awaitthis.cachePromise;
? ? returncache.match(`/avatars/${name}.jpg`);
}
}
const storage =new Storage();
storage.getAvatar('jake').then(…);//箭头函数const foo = async () = {};
2. async函数的返回值总是一个Promise
无论async函数有无await操作,其总是返回一个Promise。
1. 没有显式return,相当于return Promise.resolve(undefined);
2. return非Promise的数据data,相当于return Promise.resolve(data);
3. return Promise, 会得到Promise对象本身
async总是返回Promise,因此,其后面可以直接调用then方法,
函数内部return返回的值,会成为then回调函数的参数
函数内部抛出的错误,会被then的第二个函数或catch方法捕获到
//正常返回值asyncfunction f(){
? ? retrun 'hello world';
}
f().then(v = console.log(v));//hello world//抛出错误asyncfunction f(){
? ? thrownewError('出错了');
}
f().then(
? ? v = console.log(v),
? ? e = console.log(e)//Error: 出错了)
3. await操作符的值
[rv] = await expression(expression可以是任何值,通常是一个promise)
expression是Promise,rv等于Promise兑现的值,若Promise被拒绝,则抛出异常,由catch捕获
expression是非Promise,会被转换为立即resolve的Promise,rv等于expression
await操作只能用在async函数中,否则会报错。
4. async就是generator和promise的语法糖
//generator写法vargen =function* () {
? varf1 = yield readFile('/etc/fstab');
? varf2 = yield readFile('/etc/shells');
? console.log(f1.toString());
? console.log(f2.toString());
};//async写法varasyncReadFile = asyncfunction () {
? varf1 = await readFile('/etc/fstab');
? varf2 = await readFile('/etc/shells');
? console.log(f1.toString());
? console.log(f2.toString());
};
async就是将 generator的 * 换成 async,将 yield 换成 await。
5. async对generator的改进
1. 内置执行器
Generator必须依靠执行器调用next方法来自动执行,例如co模块。而async函数自带执行器,可以自动执行。
2. 更好的语义
async和await分别表示异步和等待,语义更加明确
3. 适用性更强
co模块后面只能是Thunk函数或Promise对象,而await后面可以是Promise或基本数据类型(如:数字,字符串,布尔等)
4. 返回Promise,可以继续操作
async函数总是返回一个Promise对象,可以对其进行then调用,继续操作后面的数据,因此,
async函数完全可以看作是多个Promise合成一个Promise对象,而await命令就是内部的then调用。
6. async内部的并行调用
async配合await都是串行调用,但是若有并行调用,则应按照以下方式来写:
1. 变量分别接收Promise
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise();
let bar = await barPromise();
2. 使用Promise.all
let [foo,bar] = await Promise.all([getFoo(),getBar()]);
Promise.all这种写法有缺陷,一个调用报错,会终止,这个不太符合并行调用的初衷。
3. 使用多个async函数
实际上,一个async函数内部包含的调用应该是强相关的,没有依赖关系的函数调用不应该放在一个async函数中,分开来逻辑更清晰。
4. 并行执行的一些写法
1. 不能再内部非async function中使用await
asyncfunction dbFuc(db) {
? let docs = [{}, {}, {}];
? // 报错,forEach的function是非async,不能使用awaitdocs.forEach(function (doc) {
? ? await db.post(doc);
? });
}//这里不需要 asyncfunction dbFuc(db) {
? let docs = [{}, {}, {}];
? // 可能得到错误结果,这样调用也不能得到正确的结果docs.forEach(asyncfunction (doc) {
? ? await db.post(doc);
? });
}
2. 循环调用await可以使用for循环或for of循环
//for ofasyncfunction dbFuc(db) {
? let docs = [{}, {}, {}];
? for (let doc of docs) {
? ? await db.post(doc);
? }
}//map + Promise.allasyncfunction dbFuc(db) {
? let docs = [{}, {}, {}];
? let promises = docs.map((doc) = db.post(doc));
? let results = await Promise.all(promises);
? console.log(results);
}//map + for ofasyncfunction dbFuc(db) {
? let docs = [{}, {}, {}];
? let promises = docs.map((doc) = db.post(doc));
? let results = [];
? for (let promise of promises) {
? ? results.push(await promise);
? }
? console.log(results);
}//for循环中去请求网页,若await操作成功,会break退出;若失败,会catch捕获,进入下一轮循环const superagent = require('superagent');
const NUM_RETRIES = 3;
async function test() {
? let i;
? for(i = 0; i NUM_RETRIES; ++i) {
? ? try {
? ? ? await superagent.get('');
? ? ? break;
? ? } catch(err) {}
? }
? console.log(i); // 3}
test();
7. async的错误处理
使用try...catch进行包裹,例如:
asyncfunction myFunction() {
? ? try {
? ? ? ? await somethingThatReturnsAPromise();
? ? } catch (err) {
? ? ? ? console.log(err);
? ? }
}
如果仅仅对一部分错误进行处理或者忽略,可以局部的进行包裹,或者对单独的promise进行catch,例如:
asyncfunction myFunction() {
? ? await somethingThatReturnsAPromise().catch((err)= {
? ? ? ? ? ? console.log(err);
? ? })
}
async function myFunction() {
? ? try{
? ? ? ? await somethingThatReturnsAPromise();
? ? }
? ? catch(e){}
? ? await somethingElse();
}
Promise的错误处理,推荐用async + await来写:
// 存值createData(title, successBack, errorBack) {
? ? // 使用key保存数据? ? storage.save({
? ? ? ? key: title,?
? ? ? ? data: 'true',
? ? }).then(successBack(), errorBack());
}
改写为
//存值async createData1(title, successBack, errorBack) {
? ? try {
? ? ? ? // 使用key保存数据? ? ? ? await storage.save({
? ? ? ? ? ? key: title,?
? ? ? ? ? ? data: 'true',
? ? ? ? });
? ? ? ? successBack()
? ? } catch (e) {
? ? ? ? errorBack()
? ? }
}
形式上更加清晰一些。
8. async函数的实现原理
async函数就是将执行器和Generator做为一个整体返回。
asyncfunction fn(){}//等同于function fn(){
? ? returnspawn(function* (){
? ? })
}
spawn的实现
function spawn(genF) {
? ? /****
? ? * 返回的是一个promise
? ? */returnnewPromise(function(resolve, reject) {
? ? ? ? vargen=genF();//运行Generator这个方法;/***
? ? ? ? * 执行下一步的方法
? ? ? ? * @param fn 一个调用Generator方法的next方法
? ? ? ? */function step(fn) {
? ? ? ? ? ? //如果有错误,则直接返回,不执行下面的awaittry {
? ? ? ? ? ? varnext=fn();
? ? ? ? ? ? }catch (e){
? ? ? ? ? ? return reject(e)
? ? ? ? ? ? }
? ? ? ? ? ? //如果下面没有yield语句,即Generator的done是trueif(next.done){
? ? ? ? ? ? return resolve(next.value);
? ? ? ? ? ? }
? ? ? ? ? ? Promise.resolve(next.value).then((val)={
? ? ? ? ? ? ? ? step(function(){return gen.next(val) } )
? ? ? ? ? ? }).catch((e)={
? ? ? ? ? ? ? ? step(function(){returngen.throw(e) } )
? ? ? ? ? ? })
? ? ? ? }
? ? ? ? step(function () {
? ? ? ? ? ? return gen.next();
? ? ? ? })
? ? });
}
参考自 async的基本用法 - 看风景就 - 博客园