Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
104 views
in Technique[技术] by (71.8m points)

javascript - Azure function typescript doesn't correctly await for a method call

I'm working on an azure function that receives requests to update an azure cosmos database. So, after receiving the request, the function read the item from database, if the item exist then it is updated accordingly. But it doesn't work as I intended, reading through the log when the function run, it seemed that the function doesn't wait until the read from database is finished. This is the snippet of the code:

const SaasWebhook: AzureFunction = function (context: Context, req: HttpRequest): Promise<void> {
    return new Promise(async (resolve, reject) => {
        // Initiate azure cosmos db
        // Get the payload information
        const subscriptionId: string = req.body?.subscriptionId;
        const action: string = req.body?.action;
        const planId: string = req.body?.planId;
        const quantity: string = req.body?.quantity;

        let patchedItem: any;
        context.log(req.body);

        try {
            // Read subscription info from the storage
            const item: Item = container.item(subscriptionId, subscriptionId);
            const { resource: readItem } = await item.read();

            context.log("Item from read: ");
            context.log(readItem);
            // Check the result, data stored in the container is formatted as 
            if (readItem.id) {
                // UPDATE ITEM here
                try {
                    // Try to write the update to the database
                    const { resource: updatedItem } = await container
                        .item(id, id)
                        .replace(patchedItem);
                    // Give success response
                    context.log("Operation success. Updated Item: ");
                    context.log(updatedItem);
                    context.res = {
                        status: 200, /* Return error status */
                        body: "Operation success."
                    };
                    resolve();
                } catch (error) {
                    context.res = {
                        status: 500, /* Return error status */
                        body: "Operation failure: Item replace failed."
                    };
                    reject(error);
                }
            }
        } catch (error) {
            context.log("Internal error: failure on accessing Database");
            context.log(error);
            context.res = {
                status: 500, /* Return error status */
                body: "Internal error: failure on accessing Database"
            };
            reject(error);
        }
    });
}

On the logger, I would get these messages printed:

2021-02-05T08:14:57.938 [Information] {THE ITEM FROM DATABASE}
2021-02-05T08:14:58.118 [Information] Item from read:
2021-02-05T08:14:58.118 [Information] undefined
2021-02-05T08:14:58.118 [Information] Internal error: failure on accessing Database
2021-02-05T08:14:58.118 [Information] TypeError: Cannot read property 'id' of undefinedat Object.<anonymous> (D:homesitewwwrootdistSaasWebhookindex.js:43:26)at Generator.next (<anonymous>)at fulfilled (D:homesitewwwrootdistSaasWebhookindex.js:5:58)at processTicksAndRejections (internal/process/task_queues.js:97:5)
2021-02-05T08:14:58.120 [Error] Executed 'Functions.SaasWebhook' (Failed, Id=ec15bf1b-d9d5-4ebc-900f-73cbc0976b41, Duration=188ms)Result: FailureException: TypeError: Cannot read property 'id' of undefinedStack: TypeError: Cannot read property 'id' of undefinedat Object.<anonymous> (D:homesitewwwrootdistSaasWebhookindex.js:43:26)at Generator.next (<anonymous>)at fulfilled (D:homesitewwwrootdistSaasWebhookindex.js:5:58)at processTicksAndRejections (internal/process/task_queues.js:97:5)

For context, this function is used as a webhook required by Microsoft marketplace SaaS fulfillment API, so the function is called again for a certain time if the call failed, the {THE ITEM FROM DATABASE} log was probably from a previous call of the function. The function is written in typescript and uploaded/deployed to azure function through Azure Function extension on Visual Studio Code. I have read that Typescript function actually got compiled into a javascript function prior to deployment, and I noticed that on the Javascript function the 'await' call was changed to 'yield', is this somehow related? And here's part of the js code that I meant:

try {
            // Read subscription info from the storage
            const item = container.item(id, id);
            const { resource: readItem } = yield item.read();
            context.log("Item from read: ");
            context.log(readItem);
...
// The rest doesn't have much difference.
...

I've also tried using item.read().then(...) instead of await and got the same result. I'm thinking to rewrite the function in plain Javascript, but I would like any of your opinions first.

question from:https://stackoverflow.com/questions/66060244/azure-function-typescript-doesnt-correctly-await-for-a-method-call

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In the end, I rewrite the function in javascript and it worked as intended. My guess was this is due to the function's compilation to javascript, the change from 'await' to 'yield' messed with the flow of the function.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...