简体   繁体   中英

Forcing an async node.js result in azure

I usually work with other programming languages, need to implement a bit of node.js code though, which I am entirely new to: For now, I just want the result of my azure function app to be actually dependent on me calling the api. I put the HTTP call into a promise and am waiting for the result:

module.exports = async function (context, req) {
    context.res = {
        body: {
            "data": [{
                "value": "start"
            }]
        }
    };
    await callapi(context);
};

function callapi(context){
    var options = {
        host: 'jsonplaceholder.typicode.com',
        port: 443,
        path: '/todos/1',
        method: 'GET'
    };
    var p1 = new Promise(
        function(resolve, reject) {
            callback = function(httpres) {
                var str = '';
                response.on('error', function (err) {
                    context.res = {body: {"data": [{"value": "error"}]}};
                });
                httpres.on('data', function (chunk) {
                   str += chunk;
                });
                httpres.on('end', function () {          
                    resolve(str);
                });
            }
            https.request(options, callback).end();
        }
    );
    p1.then(function(reqhtml) {
        context.res = {
            body: {
                "data": [{
                    "value": "it worked"
                }]
            }
        };
    })
}

My expectiation for this was that it would - depending on if the server could be reached - either return (a context with) the value "it worked" or "error", however it doesnt wait for the promise and just returns "start".

How do I wait for the async function in Azure? I do not have code outside of this; this function is only called via another API, from where I can only manipulate results in a restrained way with a graphical user interface. Is there a way to force node.js to wait inside this function?

I've cleaned up your code a bit.

module.exports = async function (context, req) {
    const value = await callapi();
    context.res = {
        body: {
            data: [{
                value
            }]
        }
    };
};

// this function does not need any parameters, 
// it's sole job is to make a https request to a static endpoint 
// and return a value based on wether there was an error or not
function callapi(){
    var options = {
        host: 'jsonplaceholder.typicode.com',
        port: 443,
        path: '/todos/1',
        method: 'GET'
    };

    return new Promise(function(resolve, reject) {
        const req = https.request(options, res => {
            let str = "";

            res.on('data', function(chunk) {
                str += chunk;
            });

            res.on('end', function() {
                resolve(str);
            });
        });

        res.on('error', reject);

        req.end();
    })
    .then(() => "it worked")
    .catch(() => "error");
}

For now, I just want the result of my azure function app to be actually dependent on me calling the api.

Since your callapi does not return anything await callapi() will await undefined and this will resolve in the next tick. (Basically, immediately after all current syncronous code has been executed and long before the Server could have sent any data back to you)

2nd: Mutating objects is frowned upon, because it's (mentally) hard to keep track of all the places that are potentially affected by this change; therefore it's dangerous. better return a copy with the changes.

3rd: keep it simple callapi does nothing where it would need to know anything about the context

The NPM library deasync solves the problem:

module.exports = async function (context, req) {    
    var uri = <uri>;
    var source = get_source_at(uri)
    context.res = { body: { "data": [{"value": source}] } };

};

function get_source_at(uri){
    var request = require("request");
    var deasync = require("deasync");
    var source;
    request({ uri:uri, headers: <headers>}
    , function (error, response, body) {
        source = body;
    });
    while(source === undefined) { //wait until async HTTPS request has finished
        deasync.runLoopOnce();
    }
    return source;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM