weixin_33717298 2018-11-09 21:55 采纳率: 0%
浏览 32

承诺:然后再解决

Very first thing I've ever done in Node.js, I'm writing an AWS Lambda function, and I want to check whether a custom attribute on a User has a value before doing anything else. Since I'm told Promises are the way to handle asynchronous methods synchronously, I wrote the function:

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

But when I run it, the console log shows "Entering function", then "Entering Promise", then the execution goes to SetId without ever having called the callback specified in adminGetUser.

If I let the debugger continue after the main flow is done, eventually I do get the logs from the callback function, so it does eventually run.

Why is the Promise skipping to the then without the resolve ever getting called?

  • 写回答

2条回答 默认 最新

  • weixin_33719619 2018-11-09 22:04
    关注

    .then accepts a function as an argument. When you do

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

    PromiseConfirmIdNotSet is called, and synchronously, SetId is called, while the interpreter tries to construct a Promise chain from the function passed to .then. (But SetId doesn't return a function) Then, after that, PromiseConfirmIdNotSet's asynchronous code runs, and the Promise resolves - which isn't in the order you want.

    Change it so that SetId is only called after the promise returned by PromiseConfirmIdNotSet resolves:

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

    The problem is similar to why

    addEventListener('click', fn());
    

    doesn't work - you'd change it to , fn); or , () => fn());.

    If you additionally want context.done to occur only after a successful SetId, then put the context.done call inside the .then:

    PromiseConfirmIdNotSet(userId)
      .then(() => {
        SetId(userId, identityId);
        context.done(null, 'Hello World');  // SUCCESS with message
      });
    
    评论

报告相同问题?

悬赏问题

  • ¥15 求解 yolo算法问题
  • ¥15 虚拟机打包apk出现错误
  • ¥30 最小化遗憾贪心算法上界
  • ¥15 用visual studi code完成html页面
  • ¥15 聚类分析或者python进行数据分析
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝