简体   繁体   中英

Define time out for node.js callback

I have a callback in node.js with S3.

Here is the code:

FS.prototype.myfunc = function (base, url, size, callBackArg) {
    var s3ForHead = new AWS.S3({httpOptions:{timeout: 5000}});

    console.log("Define s3Forhead Object");

    s3ForHead.listObjects({
        "Prefix" : url,
        "Bucket" : S3_BUCKET
    }, function (err, data) {

        console.log("Callback is done");

        if (err != null) {
            console.log(err);
            callBackArg("404");
        } else {
            if (data.Contents.length > 0) {
                callBackArg("200");
            } else {
                callBackArg("404");
            }
        });
    }
}

For some reason, The listObjects freeze sometimes in the stage of listObjects.

Meaning, Callback is done isn't printed to the screen.

I want that after 5000ms , if the callback doesn't return, I will return "404" with my callBackArg argument.

Is there any way to so it with node.js?

You need something like this:

FS.prototype.myfunc = function (base, url, size, callBackArg) {
    var s3ForHead = new AWS.S3({httpOptions:{timeout: 5000}});

    var failed = false; // failed flag
    var timeout = setTimeout(function () {
        failed = true;   // set failed flag
        callback("404"); // callback with "404"
    }, 5000);

    console.log("Define s3Forhead Object");

    s3ForHead.listObjects({
        "Prefix" : url,
        "Bucket" : S3_BUCKET
    }, function (err, data) {

        console.log("Callback is done");

        if (err != null) {
            console.log(err);
            callBackArg("404");
        } else if (!failed) { // Check if not failed

            clearTimeout(timeout); // remove the timeout if the data is ready

            if (data.Contents.length > 0) {
                callBackArg("200");
            } else {
                callBackArg("404");
            }
        });
    }
}

Well I don't think setTimeout blocks the event loop,it just queues up the function for execution after x seconds.So you could use a variable to check if the callback is fired.Also you can call the setTimeout inside the FS.prototype func but after listobjects.

FS.prototype.myfunc = function(base, url, size, callBackArg) {
    var timeout = true;//will be true before the callback is fired
    var s3ForHead = new AWS.S3({
        httpOptions: {
            timeout: 5000
        }
    });
    console.log("Define s3Forhead Object");
    s3ForHead.listObjects({
        "Prefix": url,
        "Bucket": S3_BUCKET
    }, function(err, data) {
        timeout = 'false';//set to false here since callback is fired
        console.log("Callback is done");
        if (err != null) {
            console.log(err);
            callBackArg("404");
        } else {
            if (data.Contents.length > 0)
                callBackArg("200");
            else
                callBackArg("404");
        }
    });
    setTimeout(function() {
        if (timeout) return callback("404");//Only call 404 if callback is not fired
    }, 5000);
    console.log('see settimeout does not block');//settimeout does not block,it executes callback after x secs.
};

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