承诺:然后再解决

时间:2018-11-09 21:55:05

标签: javascript node.js promise aws-lambda

我在Node.js中做过的第一件事是,我正在编写一个AWS Lambda函数,并且我想在执行其他任何操作之前检查User上的自定义属性是否具有值。因为我被告知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();
}

但是,当我运行它时,控制台日志显示“正在输入函数”,然后显示“正在输入承诺”,然后执行将转到SetId,而无需调用adminGetUser中指定的回调。

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

为什么Promise跳到那时没有调用resolve的情况下?

2 个答案:

答案 0 :(得分:1)

.then接受 function 作为参数。当你做

PromiseConfirmIdNotSet(userId)
  .then(SetId(userId, identityId))
  .catch();

PromiseConfirmIdNotSet被调用,并且同步SetId被调用,而解释器试图根据传递给{{1 }}。 (但是Promise不返回函数)然后,此后,.then的异步代码运行,并且SetId解析-顺序不理想。< / p>

对其进行更改,以使PromiseConfirmIdNotSet返回的承诺解析后,Promise仅被称为

SetId

问题与原因相似

PromiseConfirmIdNotSet

不起作用-您将其更改为PromiseConfirmIdNotSet(userId) .then(() => SetId(userId, identityId)) .catch(); addEventListener('click', fn());

如果您还希望, fn);仅在成功完成, () => fn());之后出现,则将context.done调用放在SetId内:

context.done

答案 1 :(得分:0)

您可以简单地将async-await用于整洁的异步功能。这是异步等待的代码。请检查,让我知道是否还有其他问题。

exports.handler = async function (event, context) {
 if (event != null)
 {
   var identityId = context.identity.cognitoIdentityId;

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

 await 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();
}