如何优雅地查询记录并创建它(如果它还不存在)?

时间:2018-03-13 16:11:05

标签: javascript ember.js

目标

startChat(partner_profile)的目标是获取两个用户之间聊天的ID,然后才能重定向到此聊天。 两种不同的情况

  1. 他们之间的聊天已经存在

    a)partner_profile是第一个参与者

    b)partner_profile是第二个参与者

  2. 需要首先创建他们之间的聊天
  3. 到目前为止我得到了什么

    我知道如何为上面列出的每个案例获取一个ID,但我不知道如何将它们全部合并。到目前为止,这是我的代码:

     startChat(partner_profile) {
          // case 1a
          this.get('store').queryRecord('chat', {
                  first_participant: partner_profile.id
           }).then(function(chat) {
                  let id = chat.get('id');
                  onSaveSuccess(id);
           }).catch(function(){
          });
    
          // case 1b
         this.get('store').queryRecord('chat', {
                 second_participant: partner_profile.id
         }).then(function(chat) {
                let id = chat.get('id');
                onSaveSuccess(id);
                return;
         }).catch(function(){
             // **error handling* 
        });
    
        // case 2
        let chat = this.get('store').createRecord('chat', {
            second_participant: partner_profile
        });
    
        let onSaveSuccess = (id) => this.transitionToRoute('chats.chat',id);
    
        chat.save()
            .then(function(success) {
                let id = success.get('id');
                onSaveSuccess(id);
             })
            .catch((error) => {
               // **error handling*
          }
        });
    

    如何组合这些案例?

    现在它真的很难看,因为每个案件都被执行了,当然其中有两个失败了。我怎么能以更好的方式做到这一点?有没有办法get_or_create一次记录(就像在Django中一样)? 谢谢你的帮助: - )

    编辑:更具体

    更具体地说,我有一个问题是找到一个好方法来检查我们的数据库中是否已存在聊天。见这个例子:

       let existingChat =  this.get('store').queryRecord('chat', {
          first_participant: partner_profile.id
      }).catch(function(){
    
       });
      if(!existingChat){
        // ** check for case 1b and 2
      };
    

    在此示例中,我首先查询商店以进行聊天。商店返回我保存在existingChat中的Promise,当我想检查聊天是否已存在if(!existingChat)时,尚未解决。

3 个答案:

答案 0 :(得分:2)

因此,最好的方法是首先查询该聊天,然后处理创建聊天(如果找不到)(404):

import Route from '@ember/routing/route';

export default Route.extend({
  // params is { first_participant, second_participant }
  model(params) {
    return this.store.queryRecord('chat', params)
      .catch(() => {
        // a 404 from the server would trigger a catch
        return this.store.createRecord('chat', params);
      });
  }
});

基本上这就是概念,但如果您需要创建两个聊天,它可能会更复杂。在这种情况下,您可以使用'rsvp'中的allhash助手。

import Route from '@ember/routing/route';
import { hash } from 'rsvp';

export default Route.extend({
  // params is { first_participant, second_participant }
  model(params) {
    return this.store.queryRecord('chat', params)
      .catch(() => {
        // a 404 from the server would trigger a catch
        return hash({
          chatA: this.store.createRecord('chat', { first_participant: params.first_participant }),
          chatB: this.store.createRecord('chat', { second_participant: params.second_participant })
        });
      });
  }
});

以上内容会将您的model设为{ chatA, chatB }。您需要做的承诺的复杂性还取决于您的后端API的复杂程度。有时这会让你知道你的API不是最好的。

另一个更优雅的解决方案是使用async / await。 查看本指南:https://spin.atomicobject.com/2016/12/29/async-await-ember-project/

Async / await准备好迎接黄金时段IMO。上面的例子看起来像这样:

import Route from '@ember/routing/route';

export default Route.extend({
  // params is { first_participant, second_participant }
  async model(params) {
    let chat;

    try {
      chat = await this.store.queryRecord('chat', params);
    } catch(e) {
      // a 404 from the server would trigger a catch
      chat = await this.store.createRecord('chat', params);
    }

    return chat;
  }
});

这允许您以同步方式编写异步代码,使其更易于编写和理解。

要开始使用上述内容,您需要像上面指定的博客文章那样修改ember-cli-build.js文件,即

let app = new EmberApp(defaults, {
  // Add options here
  babel: {
    includePolyfill: true
  }
});

有关详细信息,我建议使用这篇深入的文章http://rwjblue.com/2017/10/30/async-await-configuration-adventure/

答案 1 :(得分:0)

我不知道我的代码是否足够,但以下是我过去处理get_or_create的方式。

var database = [];

function getOrCreate(rowId) {
  var rowIndex = database.findIndex(r => rowId === r.Id);  
  if (rowIndex < 0) {
    database.push({
      Id: rowId
    });
    return database[database.length - 1];
  } else {
    return database[rowIndex];
  }
}

var item1 = getOrCreate(1);
var item2 = getOrCreate(2);
var item3 = getOrCreate(3);
var item4 = getOrCreate(1);

console.log(item4);

答案 2 :(得分:0)

以下是根据@ knownasilya的建议重新组织的代码:

getChatFirstParticipant().then(transitionToChat)
    .catch(() => {
      getChatSecondParticipant().then(transitionToChat)
         .catch(() => {
           createChat(partner_profile).then(transitionToChat)
             .catch((error) => {
               // ** error handling** 
             });
     });