问题描述
我有2个对象:
const subscription = {
endpoint: "dfksjfklsjkld",keys: {
pkey: "dfsfsdfsf",auth: "dfsdfsdfsd"
}
};
const extra = {
email: "dfsdfs",ip:"231342.342.342.34"
};
我想将extra
对象放入订阅中,因此它看起来像:
subsciption = {
endpoint: ......
keys: {...},extra: {
email:....,ip: .....
}
}
然后我需要将其作为http请求的正文发送:
const response = await fetch(url,{
method: "PUT",mode: "no-cors",cache: "no-cache",credentials: "same-origin",headers: {
"Content-Type": "application/json",},redirect: "follow",referrerPolicy: "no-referrer",body: JSON.stringify(subscription),});
但是我发现无论做什么,在JSON.stringify()
的过程中,我总是会丢失订阅中的额外属性。
我知道原因:这是因为额外对象中的属性不可枚举。
到目前为止,我已经尝试过:
1。使用点差:
newSub = {
...subscription,...extra
}
但是newSub的内容与其他内容完全相同,订阅的属性全部丢失。
2。将toJSON函数添加到生成额外对象的地方
getExtra() : {
.......
return {
city: ipObject.city,country: ipObject.country_name,ip: ipObject.ip,lat: ipObject.latitude,lng: ipObject.longitude,org: ipObject.org,postal: ipObject.postal,region: ipObject.region,toJSON: () => {
return this;
}
};
}
完全没有效果。
我在这里附上我的代码:
async function updateSubscription() {
try {
const allowed = await askForPermission();
if (!allowed) return;
let subscription = await getSubscription();
if (!subscription) return;
// email
const email = getEmail();
if (!email || !validateEmail(email)) {
alert("huh...so how are you going to receive notifications?");
return;
}
// ip
let ipObject = await getIP();
let extra = {};
if (ipObject) {
ipObject.email = email;
extra = ipObject;
} else {
extra.email = email;
}
console.log("extra: ",extra);
// var newSubscription = Object.assign({},subscription,{extra});
// const newSubscription = {
// ...subscription,// extra
// };
let newSubscription = subscription;
newSubscription["extra"] = extra;
console.log("new subscription1: ",newSubscription);
console.log("new subscription1 stringified: ",JSON.stringify(newSubscription));
const successful = await saveRegistration(newSubscription);
if (successful) alert("you have successfully subscribed to the DC monitor");
else alert("shit happens,try it later");
} catch (err) {
console.log("updateSubscription() failed: ",err);
}
}
async function getSubscription() {
console.log("try to get subscription");
try {
const swRegistration = await navigator.serviceWorker.ready;
const pushSubscription = await swRegistration.pushManager.getSubscription();
console.log("pushSubscription: ",pushSubscription);
return pushSubscription;
} catch (error) {
console.log("getSubscription() error: ",error);
return null;
}
}
更新
1。尝试了另外1种方法:
var newSubscription = Object.assign({},{extra});
console.log("subscription: ",newSubscription);
console.log("subscription stringified: ",JSON.stringify(newSubscription));
这是输出屏幕截图:
2。也是这个:
const newSubscription = {
...subscription,extra
};
console.log("new subscription: ",newSubscription);
console.log("new subscription stringified: ",JSON.stringify(newSubscription));
这是输出的屏幕截图:
3。使用字符串索引方法:
let newSubscription = subscription;
newSubscription["extra"] = extra;
console.log("new subscription1: ",JSON.stringify(newSubscription));
解决方法
如果可以更改subscription
,则可以使用:
subscription['extra'] = extra;
如果您要一个新对象,可以使用:
const subscriptionObject = Object.assign({},subscription,{ extra });
编辑:由于您正在使用Push API,因此无法枚举PushSubscription
中的属性。因此subscription
对象的行为与普通对象并不完全相同,这就是为什么建议的方法没有起作用的原因。
但是,您可以使用PushSubscription.toJSON()
序列化推送订阅,首先将其序列化为“普通”对象,然后使用建议的技术之一:
subscriptionObject = Object.assign({},subscription.toJSON(),{ extra });
,
您尝试过
newSub = {
...subscription,extra
}
在这种情况下,您无需进行额外传播。
sub = JSON.stringify(newSub) should result in: "{"endpoint":"dfksjfklsjkld","keys":{"pkey":"dfsfsdfsf","auth":"dfsdfsdfsd"},"extra":{"email":"dfsdfs","ip":"231342.342.342.34"}}"
,
为什么不像简单地分配属性那样使用
let subscription = {..}
const extra = {..}
然后
subscription.extra = extra;
它应该工作
,这有点棘手,但是看起来我们不知道PushSubscription
对象是如何实现的,并且它可能无法按您的预期工作...
...但是,它似乎可以使用其自己的方法(根据其API)正确转换为JSON,因此您可能需要尝试以下方法:
const newSub = { ...JSON.parse(subscription.toJSON()),extra };
因此,将其转换为JSON(使用Push API中的toJSON
方法),然后再转换回“普通” javascript对象,然后向其中添加extra
属性。