如何正确链接异步函数?
How to correctly chain async functions?
我在 ES7 中使用异步函数,包括 TypeScript、webpack 和 babel。主要的库和框架是 express
和 sequelize
.
关键配置是:
.babelrc:
{
"stage": 0,
"optional": "runtime"
}
webpack.config.js:
{test: /\.ts$/, loader: 'babel-loader!ts-loader', exclude: /node_modules/},
tsconfig.json:
{
"compilerOptions": {
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"target": "es6",
"sourceMap": true,
"experimentalDecorators": true,
"experimentalAsyncFunctions": true
},
"files": [
]
}
我正在使用 async
作为:
async function getCommentsOfVideoById(videoId: string): any {
let commentData;
ServiceLogger.info(`[VideoService]: fetching comment data.`);
commentData = await VideoComment.findAll({
where: {
vid: videoId
}
});
return commentData;
}
并将其命名为:
asyncRouter.get('/test/async/vservice', async(req, res) => {
const videoService = new VideoService();
ServiceLogger.info(`[VideServiceTest]: fetching comment data.`);
let data111;
try{
data111 = await getCommentsOfVideoById('48');
} catch (e) {
} finally {
console.log('No error');
console.log(data111);
}
res.send(data111);
});
但是返回和发送的只是[ [Function] ]
,我不太明白。而getCommentsOfVideoById
里面的日志,也就是[VideoService]: fetching comment data.
,永远不会输出。
让我感到困惑的是,类似的用法实际上是有效的。例如,我用 bluebird
:
为 http
函数编写了一个包装器
function httpGetAsync(options) {
return new bluebird.Promise(function (resolve, reject) {
console.info(`downloading from ${options}`);
http
.get(options, (res) => {
let data = '';
res.on('data', function (chunk: string) {
console.info('==========================');
console.info(chunk);
console.info('==========================');
data += chunk;
});
res.on('end', function () {
resolve(data);
});
})
.on('error', reject);
});
}
并通过链式调用异步函数进行测试:
async function a(url: string) {
console.log('[a]: start');
let result;
try {
result = await httpGetAsync(url);
//result = await divide(2, 3);
//await Promise.delay(1000);
} catch (e) {
console.log('[a]: Exception', e);
} finally {
console.log('[a]: result', result);
}
console.log('[a]: end');
return result;
}
```
```
asyncRouter.get('/test/async/nesting', async(req, res) => {
console.log('[/test/async/nesting]');
const url = req.query.url ? req.query.url : 'http://google.com/';
let response;
try {
response = await a(url);
} catch (e) {
console.log('[/test/async/nesting]: Exception', e);
} finally {
console.log('[/test/async/nesting]: response', response);
}
res.send(response);
});
它按预期工作(当您访问 http://domain/test/async/nesting?url=somewhat
时,您会被重定向)。
奇怪的是,sequelize
和我的代码都使用 bluebird
,它应该(并证明是)与 await
兼容。查看 findAll
和 Promise
的类型定义,它们都具有相同的类型签名:
///sequelize.d.ts
findAll( options? : FindOptions ) : Promise<Array<TInstance>>;
///bluebird.d.ts
declare class Promise<R> implements Promise.Thenable<R>, Promise.Inspection<R> {
constructor(callback: (resolve: (thenableOrResult: R | Promise.Thenable<R>) => void, reject: (error: any) => void) => void);
}
看来问题不在这里。但实际问题是什么?
问题似乎是 import * from bluebird as Promise
与 ES6 原生 Promise
的名称冲突。当我将该导入重命名为 bluebird
时,一切都按预期进行。
我在 ES7 中使用异步函数,包括 TypeScript、webpack 和 babel。主要的库和框架是 express
和 sequelize
.
关键配置是:
.babelrc:
{
"stage": 0,
"optional": "runtime"
}
webpack.config.js:
{test: /\.ts$/, loader: 'babel-loader!ts-loader', exclude: /node_modules/},
tsconfig.json:
{
"compilerOptions": {
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"target": "es6",
"sourceMap": true,
"experimentalDecorators": true,
"experimentalAsyncFunctions": true
},
"files": [
]
}
我正在使用 async
作为:
async function getCommentsOfVideoById(videoId: string): any {
let commentData;
ServiceLogger.info(`[VideoService]: fetching comment data.`);
commentData = await VideoComment.findAll({
where: {
vid: videoId
}
});
return commentData;
}
并将其命名为:
asyncRouter.get('/test/async/vservice', async(req, res) => {
const videoService = new VideoService();
ServiceLogger.info(`[VideServiceTest]: fetching comment data.`);
let data111;
try{
data111 = await getCommentsOfVideoById('48');
} catch (e) {
} finally {
console.log('No error');
console.log(data111);
}
res.send(data111);
});
但是返回和发送的只是[ [Function] ]
,我不太明白。而getCommentsOfVideoById
里面的日志,也就是[VideoService]: fetching comment data.
,永远不会输出。
让我感到困惑的是,类似的用法实际上是有效的。例如,我用 bluebird
:
http
函数编写了一个包装器
function httpGetAsync(options) {
return new bluebird.Promise(function (resolve, reject) {
console.info(`downloading from ${options}`);
http
.get(options, (res) => {
let data = '';
res.on('data', function (chunk: string) {
console.info('==========================');
console.info(chunk);
console.info('==========================');
data += chunk;
});
res.on('end', function () {
resolve(data);
});
})
.on('error', reject);
});
}
并通过链式调用异步函数进行测试:
async function a(url: string) {
console.log('[a]: start');
let result;
try {
result = await httpGetAsync(url);
//result = await divide(2, 3);
//await Promise.delay(1000);
} catch (e) {
console.log('[a]: Exception', e);
} finally {
console.log('[a]: result', result);
}
console.log('[a]: end');
return result;
}
```
```
asyncRouter.get('/test/async/nesting', async(req, res) => {
console.log('[/test/async/nesting]');
const url = req.query.url ? req.query.url : 'http://google.com/';
let response;
try {
response = await a(url);
} catch (e) {
console.log('[/test/async/nesting]: Exception', e);
} finally {
console.log('[/test/async/nesting]: response', response);
}
res.send(response);
});
它按预期工作(当您访问 http://domain/test/async/nesting?url=somewhat
时,您会被重定向)。
奇怪的是,sequelize
和我的代码都使用 bluebird
,它应该(并证明是)与 await
兼容。查看 findAll
和 Promise
的类型定义,它们都具有相同的类型签名:
///sequelize.d.ts
findAll( options? : FindOptions ) : Promise<Array<TInstance>>;
///bluebird.d.ts
declare class Promise<R> implements Promise.Thenable<R>, Promise.Inspection<R> {
constructor(callback: (resolve: (thenableOrResult: R | Promise.Thenable<R>) => void, reject: (error: any) => void) => void);
}
看来问题不在这里。但实际问题是什么?
问题似乎是 import * from bluebird as Promise
与 ES6 原生 Promise
的名称冲突。当我将该导入重命名为 bluebird
时,一切都按预期进行。