等到数据返回,带有角度和微风的同步调用

时间:2015-04-22 21:02:11

标签: javascript angularjs promise breeze

我正在开发一个小型博客引擎,用户可以在其中创建博客条目,并可以将标签链接到条目。它是多对多关系,但由于Breeze无法管理这种关系,我必须将连接表暴露给微风,以便我可以逐步保持数据。我的问题就在这里。

表格

  • BlogEntry
  • BlogEntryTag
  • 标签

方案

  • 用户打开"新博客条目"表格或选择要编辑的现有文件
  • 输入文字等
  • 选择一个或多个标签

商业逻辑

  • 通过Breeze创建一个新实体/查询所选实体
  • 保存博客条目(第一次服务器调用,如果博客条目是新条目,则返回blog_id)
  • 检查标签和博客条目之间已存在的连接,如果编辑了博客条目,则现有的blogEntry-tag关系可能会发生变化(第二次服务器调用)
  • 基于标签名称从标签表中选择tag_id(第三服务器调用)
  • 通过breeze
  • 创建BlogEntrytag实体
  • 将BlogEntrytag实体保留在数据库中(第4次服务器调用)

我认为订单必须是连续的。

我有这段代码,您可以看到附带的屏幕截图,控制台日志标记为' _blogEntryEnttity'不要等到数据从服务器返回,并且它将在控制台记录之前执行,该记录由' _blogEntryEnttity标记为'。当代码尝试稍后设置title属性时,代码将抛出引用异常。

var blogEntryEntityQueryPromise = datacontext.blogentry.getById(_blogsObject.id);

                    blogEntryEntityQueryPromise.then(function (result)
                    {
                        console.log('result', result);
                        _blogEntryEntity = result[0];
                        console.log('_blogEntryEnttity inside', _blogEntryEntity);
                        //if I need synchronous execution then I have to put the code here which must be executed consecutively
                    });
                    console.log('_blogEntryEnttity', _blogEntryEntity);
                }

                //mapping the values we got
                _blogEntryEntity.title = _blogsObject.title;
                _blogEntryEntity.leadWithMarkup = _blogsObject.leadWithMarkup;
                _blogEntryEntity.leadWithoutMarkup = _blogsObject.leadWithoutMarkup;
                _blogEntryEntity.bodyWithMarkup = _blogsObject.bodyWithMarkup;
                _blogEntryEntity.bodyWithoutMarkup = _blogsObject.bodyWithoutMarkup;
                console.log('_blogEntryEnttity', _blogEntryEntity);

示例来自here

我的问题是,为什么不等到数据回来?处理此类案件的方式是什么?

但是,我发现,如果我需要同步执行,那么我应该在从promise中检索数据之后将代码放入success方法中。但是,我真的不喜欢这个解决方案,因为我的代码会在一段时间后难以维护。

datacontext.blogentry.getById如下所示,实现在抽象类中,您也可以在下面找到代码。整个存储库模式来自John Papa在Pluralsight上的course

存储库类方法

function getById(id)
        {

            return this._getById(this.entityName, id);
        }

抽象存储库类方法。根据{{​​3}} EntityQuery类' execute方法返回一个Promise。

function _getById(resource, id) {

            var self = this;
            var manager = self.newManager;
            var Predicate = breeze.Predicate;
            var p1 = new Predicate('id', '==', id);

            return EntityQuery.from(resource)
                .where(p1)
                .using(manager).execute()
                .then(success).catch(_queryFailed);

            function success(data) {
                return data.results;
            }
        }

Execution order

我提前感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

我认为你不需要所有这些往返旅行。我这样做:

  1. 查询所有可用的标记实体,以便它们位于EntityManager的缓存中(无论如何都需要填充这些实体)。

  2. 如果它是现有的BlogEntry,只需查询BlogEntry及其所有相关的BlogEntryTag实体; Breeze会将BlogEntryTags连接到缓存中的关联标签。如果用户选择/取消选择BlogEntry的标签,您将添加/删除BlogEntryTags。

  3. var query = EntityQuery.from("BlogEntries").where("id", "==", id).expand("BlogEntryTags");

    1. 如果它是一个新的BlogEntry,它就不会有任何BlogEntryTags。在用户选择一些标签后,您可以在保存时创建这些标记。

    2. 在一次saveChanges电话中将添加/更新的BlogEntry和任何已添加/删除的BlogEntryTag实体保存到数据库中。

    3. 请参阅Presenting Many-to-Many文档及其associated plunker进行更深入的了解。用户界面与您想要的不同,但基础概念很有用。

答案 1 :(得分:1)

  

为什么不等到数据回来?

因为承诺不会神奇地同步执行。他们仍然是异步的,他们still rely on callbacks

  

处理此类案件的方式是什么?

您需要在then回调中放置应该等待的代码。

  

但是,我真的不喜欢这个解决方案,因为我的代码会在一段时间后难以维护。

实际上,您可以使用promises编写简洁优雅的异步代码。如果你的代码变得太过意大利面,那么它的抽象部分就是自己的功能。你应该能够进入干净的flat承诺链。