如何正确地链接异步函数



我在ES7中使用异步函数,包括TypeScript、webpack和babel。主要的库和框架是expresssequelize

关键配置包括:

.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兼容。查看findAllPromise的类型定义,它们都具有相同的类型签名:

///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时,一切都如预期的那样进行。

最新更新