Javascript 如果记录还不存在,如何优雅地查询并创建它? 目标
Javascript 如果记录还不存在,如何优雅地查询并创建它? 目标,javascript,ember.js,Javascript,Ember.js,startChat(partner_profile)的目标是获取两个用户之间聊天的id,然后能够重定向到此聊天。 有两种不同的情况: 他们之间的聊天已经存在 a) partner\u profile是第一个参与者 b) partner\u profile是第二个参与者 首先需要创建他们之间的聊天 到目前为止我得到了什么 我知道如何获得上面列出的每一个案例的ID,但我不知道如何将它们结合起来。以下是我目前的代码: startChat(合作伙伴档案){ //案例1a this.get('store'
startChat(partner_profile)
的目标是获取两个用户之间聊天的id,然后能够重定向到此聊天。
有两种不同的情况:
partner\u profile
是第一个参与者
b) partner\u profile
是第二个参与者startChat(合作伙伴档案){
//案例1a
this.get('store').queryRecord('chat'{
第一个参与者:partner\u profile.id
}).然后(功能(聊天){
let id=chat.get('id');
onSaveSuccess(id);
}).catch(函数(){
});
//案例1b
this.get('store').queryRecord('chat'{
第二个参与者:partner_profile.id
}).然后(功能(聊天){
let id=chat.get('id');
onSaveSuccess(id);
返回;
}).catch(函数(){
//**错误处理*
});
//案例2
let chat=this.get('store').createRecord('chat'{
第二名参与者:合作伙伴简介
});
让onSaveSuccess=(id)=>this.transitionRoute('chats.chat',id);
chat.save()
.然后(功能(成功){
让id=success.get('id');
onSaveSuccess(id);
})
.catch((错误)=>{
//**错误处理*
}
});
我如何合并这些案例?
现在真的很难看,因为每个案子都被执行了,当然有两个失败了。我怎么能做得更好呢?有没有一种方法可以一次获取或创建一个记录(就像Django中的记录)?
谢谢您的帮助:-)
编辑:更具体
更具体地说,我有一个问题,找到一个好方法来检查聊天是否已经存在于我们的数据库中。请参见此示例:
let existingChat = this.get('store').queryRecord('chat', {
first_participant: partner_profile.id
}).catch(function(){
});
if(!existingChat){
// ** check for case 1b and 2
};
在本例中,我首先查询商店中的聊天记录。商店返回我保存在
existingChat
中的承诺,当我想用if(!existingChat)
检查聊天是否已经存在时,该承诺尚未解决 我不知道我是否有足够的代码,但以下是我过去如何处理get\u或\u create
var数据库=[];
函数getOrCreate(rowId){
var rowIndex=database.findIndex(r=>rowId==r.Id);
如果(行索引<0){
database.push({
Id:rowId
});
返回数据库[database.length-1];
}否则{
返回数据库[rowIndex];
}
}
var item1=getOrCreate(1);
var item2=getOrCreate(2);
var item3=getOrCreate(3);
var item4=getOrCreate(1);
控制台日志(第4项)代码>因此,最好的方法是首先查询该聊天,然后在找不到该聊天时处理创建该聊天(404):
基本上,这是一个概念,但是如果你需要创建两个聊天室,它可能会更复杂。在这种情况下,您可以使用“rsvp”中的all
或hash
帮助程序
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 })
});
});
}
});
上面将您的模型设置为{chatA,chatB}
。您需要如何实现承诺的复杂性还取决于后端API的复杂性。有时,这是一种让您知道您的API不是最好的API的气味
另一个更优雅的解决方案是使用async/await。
查看本指南:
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
}
});
有关更多详细信息,我推荐这篇深入的文章以下是根据@knownasilya的建议重新组织的代码:
getChatFirstParticipant().then(transitionToChat)
.catch(() => {
getChatSecondParticipant().then(transitionToChat)
.catch(() => {
createChat(partner_profile).then(transitionToChat)
.catch((error) => {
// ** error handling**
});
});
谢谢你的回答!遗憾的是,你的回答对我没有帮助,但这是我的责任。我应该更具体地描述我的问题。我不知道我可以在if中插入什么(检查对象是否已经存在)。余烬存储返回一个承诺,因此如果(!existingChat)
不起作用,则让existingChat=this.get('store').queryRecord(…)。我将扩展我的问题。我不需要创建两个不同的聊天。我只需要以两种不同的方式查询现有聊天(因为聊天伙伴可以保存为第一个参与者
或第二个参与者
)。你是对的,API在这里有点麻烦,但是我继承了这段代码,现在修改它需要花费太多的时间。谢谢你,它为我工作了!现在我有了结构良好的代码@Whiterose我已经更新了我的答案,添加了另一个更优雅的解决方案。谢谢你的更新!我刚看到,抱歉耽搁了。我在研究答案时偶然发现了wait
,但没有使用它,因为如果我理解正确,它在Ember中还没有得到官方支持。此外,我还需要能够支持较旧的浏览器(在您提供的深入文章中指出,从10月17日起,仅支持流行浏览器的最后两个版本)。但这让我充满希望,在未来,我们将不再需要如此丑陋的捕获链^^^^使用babelPolyfill,您不必担心浏览器兼容性,因为它将代码更改为所有当前浏览器都支持的格式。
getChatFirstParticipant().then(transitionToChat)
.catch(() => {
getChatSecondParticipant().then(transitionToChat)
.catch(() => {
createChat(partner_profile).then(transitionToChat)
.catch((error) => {
// ** error handling**
});
});