I have 2 objects:
const subscription = {
endpoint: "dfksjfklsjkld",
keys: {
pkey: "dfsfsdfsf",
auth: "dfsdfsdfsd"
}
};
const extra = {
email: "dfsdfs",
ip:"231342.342.342.34"
};
I would like to put the extra
object inside subscription, so it looks like:
subsciption = {
endpoint: ......
keys: {...},
extra: {
email:....,
ip: .....
}
}
then I need to send it as body of a http request:
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),
});
but I found no matter what I do, I always lose the extra property inside subscription in the process of JSON.stringify()
.
I know the cause: it's because that the properties in extra object are not enumerable.
So far, I have tried:
1.use the spread:
newSub = {
...subscription,
...extra
}
but the content of newSub will be exactly same with extra, the properties of subscription are all lost.
2.add toJSON function into the place where I generate the extra object
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;
}
};
}
no effect at all.
I attach my code here:
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.Tried 1 more approach:
var newSubscription = Object.assign({}, subscription, {extra});
console.log("subscription: ", newSubscription);
console.log("subscription stringified: ", JSON.stringify(newSubscription));
here is the output screenshot:
2.Also this one:
const newSubscription = {
...subscription,
extra
};
console.log("new subscription: ", newSubscription);
console.log("new subscription stringified: ", JSON.stringify(newSubscription));
And here is the screenshot of output:
3.with string index approach:
let newSubscription = subscription;
newSubscription["extra"] = extra;
console.log("new subscription1: ", newSubscription);
console.log("new subscription1 stringified: ", JSON.stringify(newSubscription));
If mutating subscription
is OK, you can just use:
subscription['extra'] = extra;
If you want a new object, you can use:
const subscriptionObject = Object.assign({}, subscription, { extra });
EDIT: Since you are working with the Push API , the properties in PushSubscription
are not enumerable. So the subscription
object does not behave quite like a normal object, which is why the suggested approaches have not been working.
However, you can serialize the push subscription using PushSubscription.toJSON()
first to serialize it to a "normal" object, then use one of the suggested techniques:
subscriptionObject = Object.assign({}, subscription.toJSON(), { extra });
This is a bit hacky, but it looks like we don't know how the PushSubscription
object is implemented, and it may not work as you expect...
... however it seems to convert to JSON properly using its own method (according to its API), so you may want to try something like this:
const newSub = { ...JSON.parse(subscription.toJSON()), extra };
Thus, converting it to JSON (using the toJSON
method in the Push API) and back to a "normal" javascript object, -then- adding the extra
property to it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.