承诺不解决快递中间件中的异步功能内部

时间:2019-09-24 01:03:07

标签: node.js typescript express promise async-await

这一个开始在我的皮肤下...

我现在正在玩Firebase和Functions,并制作了一个非常简单的API,以express作为中间件。

所以我有这条路线:

...

app.get('/getAuthUrl', async (req, res) => {
  const s: sessionManagement.ISessionManagement = 
    sessionManagement.SessionFactory.createSession(
      functions.config().aproxy.session.mode, req, db)

  // ...this work
  const getback = req.query.getback;
  await db.collection('tokens').doc('getback').set({getback});

  // this not?!
  s.setReturnURL(req.query.getback);

  res.setHeader('Cache-Control', 'private');
  res.status(200).json(new Message(redirectUri));
})

首先,我在注释“ ... this work”下使用两行,它确实起作用;将网址写入Firestore数据库。到目前为止,一切都很好。

然后,我决定变得幻想起来,并决定使用对象工厂来管理以下事实:在一个端口上(通过仿真器)在提供服务的本地主机上使用Express会话,而在另一个端口上使用有角度的前端在会话上造成了一些麻烦管理。简而言之,我设置了一个工厂,该工厂将为我返回一个对象,该对象将在本地运行或在Firebase云托管上使用其他策略进行管理。

这是Promise开始不履行承诺的地方!?

s.setReturnURL(..行在我的工厂内调用此方法:

export interface ISessionManagement {
    setReturnURL: (value: string) => void
}

export class FirestoreSession implements ISessionManagement {
    private database: FirebaseFirestore.Firestore
    private fingerprint: string

    constructor(database: FirebaseFirestore.Firestore, fingerprint: string) {
        this.database = database
        this.fingerprint = fingerprint
    }

    setReturnURL(value: string) {
        console.log('setReturnURL')
        this.writeDoc(value, 'getback')
    }

    writeDoc(value: string, document: string) {
        (async () => {
            console.log('inside async')
            const doc = this.database.collection('tokens').doc(document).set({value})
            const result = await doc
            console.log(result)
        })().catch(error => {
            console.log(error)
        })
        console.log('finish writeDoc')
    }
}

export class SessionFactory {
    public static createSession(mode: string, req: express.Request, db: FirebaseFirestore.Firestore) : ISessionManagement {
        if (mode === 'fingerprint' ) {
            console.log('fingerprint mode');
            // Use for local testing, since in multiport solution, cookie will not be unique to a session
            return new FirestoreSession(db, fingerPrintMe(req));
        } else {
            // For production
            return new ExpressSession(req);
        }
    }
}

因此,如果使用我的工厂对象,则在此处执行流程的控制台输出:

✔  functions[app]: http function initialized (http://localhost:5000/myplayground/us-central1/app).
i  functions: Beginning execution of "app"
>  fingerprint mode
>  setReturnURL
>  inside async
>  finish writeDoc
i  functions: Finished "app" in ~1s

上面的代码是我最近使此工作成功的尝试。我尝试了很多变化,将我的异步/等待动了一下,但没有任何动静!

我想念什么???我觉得答案会让我有些难为情,但我不在乎,我需要把这一个放在心上:-)

更新

结果是,我需要一直进行异步/等待,直到返回一个保证完成这项工作的承诺的调用,而且,您也不能等待返回void的函数,所以我不得不更改接口签名。所以这里的代码片段有效:

app.get('/getAuthUrl', async (req, res) => {
  ... 

  await s.setReturnURL(req.query.getback)

  ...
})

...

export interface ISessionManagement {
    setReturnURL: (value: string) => any 
}

export class FirestoreSession implements ISessionManagement {

    ...

    async setReturnURL(value: string) {
        await this.writeDoc(value, 'getback')
    }

    ...

    async writeDoc(value: string, document: string) {
        try {
            const doc = await this.database.collection('tokens').doc(document).set({value})
            console.log(doc)
        } catch (error) {
            console.log(error)            
        }
    }
}

1 个答案:

答案 0 :(得分:0)

const doc = this.database.collection('tokens').doc(document).set({value})
const result = await doc

为什么不只是const result = await this.database.collection('tokens').doc(document).set({value})

`writeDoc(value: string, document: string) {
        (async () => {
            console.log('inside async')
            const doc = this.database.collection('tokens').doc(document).set({value})
            const result = await doc
            console.log(result)
        })().catch(error => {
            console.log(error)
        })
        console.log('finish writeDoc')
    }`

首先,writedoc不是一个承诺,也没有等待。内部异步函数也不会等待,因此一旦执行暂停,该函数的其余部分就会继续前进。因此它将执行,并且内部异步功能的其余部分将排队等待下一个事件循环。然后一切都返回并退出。

使writedoc异步,然后等待它和内部异步功能。