承诺:然后在解决之前

Tre*_*tni 1 javascript node.js promise aws-lambda

我在 Node.js 中做过的第一件事,我正在编写一个 AWS Lambda 函数,我想在做任何其他事情之前检查用户的自定义属性是否有值。因为我被告知 Promises 是同步处理异步方法的方式,所以我写了这个函数:

var AWS = require('aws-sdk');
var s3 = new AWS.S3();
var cogId = new AWS.CognitoIdentityServiceProvider();

exports.handler = function (event, context) {

    if (event != null)
    {
        var identityId = context.identity.cognitoIdentityId;

        if (event.userId != null)
        {
            var userId = event.userId;
            PromiseConfirmIdNotSet(userId)
                .then(SetId(userId, identityId))
                .catch();
        }
    }

    context.done(null, 'Hello World');  // SUCCESS with message
};

function PromiseConfirmIdNotSet(userId)
{
    console.log('Entering function');
    return new Promise(function (resolve, reject) {
        console.log('Entering Promise');
        cogId.adminGetUser({
                UserPoolId: myUserPool,
                UserId: userId
            },
            function (err, data) {
                console.log('err = ' + JSON.stringify(err));
                console.log('data = ' + JSON.stringify(err));
                if (data != null && data.UserAttributes.Name == null) {
                    console.log('Calling resolve');
                    resolve();
                } else {
                    console.log('Calling reject');
                    reject();
                }
            });
    });
    console.log('Exiting Promise');
}

function SetId(userId, identityId)
{
    cogId.updateUserAttributes();
}
Run Code Online (Sandbox Code Playgroud)

但是当我运行它时,控制台日志显示“进入函数”,然后是“进入承诺”,然后执行就SetId没有调用adminGetUser.

如果在主流程完成后让调试器继续运行,最终我会从回调函数中获取日志,因此它最终会运行。

为什么 Promise 会跳到 then 而resolve没有被调用?

Cer*_*nce 5

.then接受一个函数作为参数。当你做

PromiseConfirmIdNotSet(userId)
  .then(SetId(userId, identityId))
  .catch();
Run Code Online (Sandbox Code Playgroud)

PromiseConfirmIdNotSet被调用,并且同步地SetId被调用,而解释器尝试构建一个Promise链从功能传递给.then。(但SetId不返回函数)然后,之后,PromiseConfirmIdNotSet的异步代码运行,并Promise解析 - 这不是您想要的顺序。

更改它,以便SetIdresolves 返回的承诺之后调用PromiseConfirmIdNotSet

PromiseConfirmIdNotSet(userId)
  .then(() => SetId(userId, identityId))
  .catch();
Run Code Online (Sandbox Code Playgroud)

问题类似于为什么

addEventListener('click', fn());
Run Code Online (Sandbox Code Playgroud)

不起作用 - 您将其更改为, fn);, () => fn());

如果您还想context.done仅在成功后才发生SetId,则将context.done调用放在.then

PromiseConfirmIdNotSet(userId)
  .then(() => {
    SetId(userId, identityId);
    context.done(null, 'Hello World');  // SUCCESS with message
  });
Run Code Online (Sandbox Code Playgroud)