最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How does promise work in Node.js and AWS lambda functions - Stack Overflow

programmeradmin2浏览0评论

I am very new to Javascript and Node.js in general . As such i am trying to get my head around the concept of asynchronous programming in Node.js and also how to use the same in AWS lambda.

I came across this blog post on Amazon blogs which explains the support for async/await in Node.js lambda functions : /

So far as i knew the concept of a function generating a promise is as in the below code snippet:

const func1 = () => {
    console.log("Starting with execution of func1...")
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("First promise ended after 3 secs")
        }, 3000)
    })
}

So in here the function explicitly generates a Promise and returns the same.

But in the above AWS blog post i see a function definition as such :

let AWS = require('aws-sdk');
let lambda = new AWS.Lambda();

exports.handler = async (event) => {
    return await lambda.getAccountSettings().promise() ;
};

Now i have checked the AWS SDK for Node.js documentation (.html#getAccountSettings-property) and i see that the function getAccountSettings accepts a callback as the third parameter.

I am confused with the .promise() syntax of generating promises .How does a function ensure that using that syntax it would give back a promise object . Because from the docs there is no mention that if i use .promise() it would return a promise instead. I am assuming there might be a rule of thumb here in this aspect.

Also instead of return await lambda.getAccountSettings().promise() if i just write return await lambda.getAccountSettings() what difference would it make .

Is there any documentation on this that i can refer to ?

Request you to please throw some more light on this new way of getting promise object back.

Thanks for any help in advance.

I am very new to Javascript and Node.js in general . As such i am trying to get my head around the concept of asynchronous programming in Node.js and also how to use the same in AWS lambda.

I came across this blog post on Amazon blogs which explains the support for async/await in Node.js lambda functions : https://aws.amazon./blogs/pute/node-js-8-10-runtime-now-available-in-aws-lambda/

So far as i knew the concept of a function generating a promise is as in the below code snippet:

const func1 = () => {
    console.log("Starting with execution of func1...")
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("First promise ended after 3 secs")
        }, 3000)
    })
}

So in here the function explicitly generates a Promise and returns the same.

But in the above AWS blog post i see a function definition as such :

let AWS = require('aws-sdk');
let lambda = new AWS.Lambda();

exports.handler = async (event) => {
    return await lambda.getAccountSettings().promise() ;
};

Now i have checked the AWS SDK for Node.js documentation (https://docs.aws.amazon./AWSJavaScriptSDK/latest/AWS/Lambda.html#getAccountSettings-property) and i see that the function getAccountSettings accepts a callback as the third parameter.

I am confused with the .promise() syntax of generating promises .How does a function ensure that using that syntax it would give back a promise object . Because from the docs there is no mention that if i use .promise() it would return a promise instead. I am assuming there might be a rule of thumb here in this aspect.

Also instead of return await lambda.getAccountSettings().promise() if i just write return await lambda.getAccountSettings() what difference would it make .

Is there any documentation on this that i can refer to ?

Request you to please throw some more light on this new way of getting promise object back.

Thanks for any help in advance.

Share Improve this question asked Sep 29, 2019 at 9:45 Subhayan BhattacharyaSubhayan Bhattacharya 5,72310 gold badges48 silver badges70 bronze badges 10
  • 1 Stack Overflow is not the right place to ask for documentation, but aws.amazon./blogs/pute/… just describes promise support that was added later, which explains why you have this "double" support (callback or promise). If you still have a programming question, please revise your question so it is specific about that, and not about (documentation) resources. – trincot Commented Sep 29, 2019 at 9:52
  • Hello Trincot i have read this link and this what confused me in the first place . I am just not sure about the new syntax of getting a promise back. – Subhayan Bhattacharya Commented Sep 29, 2019 at 9:54
  • 1 But you seem to know the syntax, since you use it? The promise API is described in the quite obscure EcmaScript specs, or more simple in the Promises/A+ specs. AWS .promise() ensures that "protocol" is properly implemented, so you can trust that await and .then will work as in those specs. – trincot Commented Sep 29, 2019 at 9:57
  • 1 Is your question about implementing something similar to what AWS offers with its .promise() method, and not about using the AWS promise-API? Sorry, I don't really understand what you are looking for. – trincot Commented Sep 30, 2019 at 19:43
  • 1 Is there any documentation on this that i can refer to ? - yes. If you open the link you posted above. The getAccountSettings documentation. You will see that it returns an AWS.Request object. Click on it then read the documentation of AWS.Request (the thing it returns). Scroll down until you see the methods defined for AWS.Request and you will see a method promise() (under the section "Sending a Request". That's the documentation – slebetman Commented Sep 30, 2019 at 21:10
 |  Show 5 more ments

1 Answer 1

Reset to default 9

If you would like to understand why the .promise() method was made available, and why the promise was not just returned just-like-that, note how such an API evolves over time, and backwards patibility must be maintained.

Let's build something similar, but much simplified. Let's make a function that provides 1/x for a given number, but an error object when x=0. This will be done asynchronously.

Also, we want the function to return synchronously an object that allows one to register a listener for when an error occurs, another for when there is success, and yet another when either of the two happens. This is a much simplified idea from what AWS returns: there you get a very rich Request object.

So imagine we are in 2012 and promises are not yet widely available/used in JavaScript. So we provide the following API for our asynchronous 1/x function:

// Implementation in the first version of the API (without promises):
//    * returns an object with which you can register a listener
//    * accepts an optional callback
function getAsyncInverse(num, callback) {
    var onSuccess = [], // callbacks that are called on success
        onError = [], // callbacks that are called on failure
        onComplete = [];  // callbacks that are called in both situations
    if (callback) onComplete.push(callback);
    
    function plete(err=null) {
        var result = null;
        if (num === 0) err = new Error("Division by Zero");
        else result = 1/num;
        // Communicate the result/error to the appropriate listeners:
        if (err) for (var i = 0; i < onError.length; i++) onError[i](err);
        else for (var i = 0; i < onSuccess.length; i++) onSuccess[i](result);
        for (var i = 0; i < onComplete.length; i++) onComplete[i](err, result);
    }

    var timeoutId = setTimeout(plete, 100);

    var request = {
        on: function (type, callback) {
            if (type === "success") onSuccess.push(callback);
            else if (type === "error") onError.push(callback);
            else if (type === "plete") onComplete.push(callback);
            return request;
        },
        abort: function () {
            clearTimeout(timeoutId);
            plete(new Error("aborted"));
            return request;
        }
    }
    
    return request;
}

// How version 1 is used, by registering a listener via the returned object
var num = 2;
var request = getAsyncInverse(num); // let's not pass a callback here
request.on("success", function (result) { // ... but use the request object
    console.log("The result is:", result);    
}).on("error", function (err) {
    console.log("There was an error:", err);
});

But then promises bee more popular and users of your API are pushing for a promise API. You want to ensure backwards patibility, and so decide to just extend the returned request-object with one additional property, a method: promise()

Here is how the above implementation would be altered to make that happen:

// Implementation in the second version of the API (with promise), but backwards-patible
//    * returns an object with which you can register a listener, or get the promise object
//    * accepts an optional callback
function getAsyncInverse(num, callback) {
    let onSuccess = [], // callbacks that are called on success
        onError = [], // callbacks that are called on failure
        onComplete = [];  // callbacks that are called in both situations
    if (callback) onComplete.push(callback);
    
    let request;
    // New: create a promise, and put the logic inside the promise-constructor callback
    let promise = new Promise(function (resolve, reject) {
        function plete(err=null) {
            let result = null;
            if (num === 0) err = new Error("Division by Zero");
            else result = 1/num;
            // Communicate the result/error to the appropriate listeners:
            if (err) for (let callback of onError) callback(err);
            else for (let callback of onSuccess) callback(result);
            for (let callback of onComplete) callback(err, result);
            // New: also call resolve/reject
            if (err) reject(err);
            else resolve(result);
        }

        let timeoutId = setTimeout(plete, 100);
        
        request = {
            on: function (type, callback) {
                if (type === "success") onSuccess.push(callback);
                else if (type === "error") onError.push(callback);
                else if (type === "plete") onComplete.push(callback);
                return request;
            },
            abort: function () {
                clearTimeout(timeoutId);
                plete(new Error("aborted"));
                return request;
            },
            promise: function () { // <--- added feature!
                return promise;
            }
        };
    });

    return request; // We return the same as in version-1, but with additional promise method
}

// How version 2 is used, by getting the new promise method
let num = 2;
let promise = getAsyncInverse(num).promise();
promise.then(function (result) {
    console.log("The result is:", result);    
}).catch(function (err) {
    console.log("There was an error:", err);
});

As you can see, it would not be a good idea to omit the request object, and have the function return the promise. This would break existing code using your API (no backwards patibility).

发布评论

评论列表(0)

  1. 暂无评论