problem description
I"m using Angular to build a client, hoping to get the latest real-time prices from the server by clicking on the following items on the page. But when I click the client button, I report the exception of core.js:1633 ERROR SyntaxError: Unexpected token in JSON at position 0. Browser debugging errors are as follows:
has been bothering me for two days. I can find a way to try on the Internet, but I can"t solve it. It is said that it is possible to use JSON to convert client and server data in the wrong format of JSON.stringify and JSON.parse. But I still can"t find it. Ask the bosses for help.
related codes
client
product-detail.component.html
<div class="thumbnail">
<img src="http://temp.im/820x300">
<div>
<h4 class="pull-right">{{product?.price}}</h4>
<h4>{{product?.price}}</h4>
{{product?.desc}}
</div>
<div>
<p class="pull-right">{{comments?.length}}
<app-stars [rating]="product?.rating"></app-stars>
</div>
</div>
<div class="thumbnail">
<button class="btn btn-default btn-lg" [class.active]="isWatched" (click)="watchProduct()">
{{isWatched?"":""}}
</button>
<label>:{{currentBid | number:".2-2"}}</label>
</div>
<div class="well">
<div>
<button class="btn btn-success" (click)="isCommentHidden = !isCommentHidden"></button>
</div>
<div [hidden]="isCommentHidden">
<div><app-stars [(rating)]="newRating" [readonly]="false"></app-stars></div>
<div><textarea [(ngModel)]="newComment"></textarea></div>
<div><button class="btn" (click)="addComment()"></button></div>
</div>
<div class="row" *ngFor="let comment of comments">
<hr>
<div class="col-md-12">
<app-stars [rating]="comment.rating"></app-stars>
<span>{{comment.user}}</span>
<span class="pull-right">{{comment.timestamp}}</span>
{{comment.content}}
</div>
</div>
</div>
product-detail.component.ts
import { Component, OnInit } from "@angular/core";
import {ActivatedRoute} from "@angular/router";
import {Comment, Product, ProductService} from "../shared/product.service";
import {WeSocketService} from "../shared/we-socket.service";
@Component({
selector: "app-product-detail",
templateUrl: "./product-detail.component.html",
styleUrls: ["./product-detail.component.css"]
})
export class ProductDetailComponent implements OnInit {
product: Product;
comments: Comment [];
isWatched: boolean = false;
currentBid: number;
newRating: number = 5;
newComment: string = "";
isCommentHidden: boolean = true;
constructor(private routInfo: ActivatedRoute,
private productService: ProductService,
private webService: WeSocketService
) { }
ngOnInit() {
let productId: number = this.routInfo.snapshot.params["productId"];
this.productService.getProduct(productId).subscribe(
product => {
this.product = product;
this.currentBid = this.product.price;
}
);
this.productService.getProductForProductId(productId).subscribe(
comment => this.comments = comment
);
}
addComment() {
let comment = new Comment(0, this.product.id, new Date().toISOString(), "SomeOne", this.newRating, this.newComment);
this.comments.unshift(comment);
let sum = this.comments.reduce((sum, comment) => sum + comment.rating, 0);
this.product.rating = sum / this.comments.length;
this.newComment = null;
this.newRating = 5;
this.isCommentHidden = true;
}
watchProduct() {
this.isWatched = !this.isWatched;
this.webService.creatObservableSocket("ws://localhost:8085", this.product.id)
.subscribe(
products => {
let produc = products.find(p => p.productId === this.product.id);
this.currentBid = produc.bid;
}
);
}
}
we-socket.service.ts
import { Injectable } from "@angular/core";
import {observable, Observable} from "rxjs";
import "rxjs/Rx";
@Injectable({
providedIn: "root"
})
export class WeSocketService {
ws: WebSocket;
constructor() { }
creatObservableSocket(url: string, id: number): Observable<any> {
this.ws = new WebSocket(url);
return new Observable<string>(
observable => {
this.ws.onmessage = (event) => observable.next(event.data);
this.ws.onerror = (event) => observable.error(event);
this.ws.onclose = (event) => observable.complete();
this.ws.onopen = (event) => this.sendMessage({productId: id});
}
).map(message => {JSON.parse(message)});
}
sendMessage(message: any) {
this.ws.send(JSON.stringify(message));
}
}
Server
auction_service.ts
import * as express from "express";
import {Server} from "ws";
const app = express();
export class Product {
constructor(
public id: number,
public title: string,
public price: number,
public rating: number,
public desc: string,
public categories: Array<string>
) {
}
}
export class Comment {
constructor(
public id: number,
public productId: number,
public timestamp: string,
public user: string,
public rating: number,
public content: string
) {
}
}
const products: Product[] = [
new Product(1, "", 1.99, 1.5, "Angular", ["", ""]),
new Product(2, "", 2.99, 3.5, "Angular", [ ""]),
new Product(3, "", 3.99, 4.5, "Angular", ["", ""]),
new Product(4, "", 4.99, 2.5, "Angular", [""]),
new Product(5, "", 5.99, 1.5, "Angular", ["", ""]),
new Product(6, "", 6.99, 3.5, "Angular", [""]),
];
const comments: Comment[] = [
new Comment(1, 1, "2018-02-22 1:15:13", "", 3, "~"),
new Comment(2, 1, "2018-03-02 21:15:13", "", 2, "~"),
new Comment(3, 1, "2018-06-22 15:12:03", "", 4, "~"),
new Comment(4, 2, "2018-04-22 17:20:13", "", 1, ""),
new Comment(5, 2, "2018-07-22 11:15:13", "", 4, ""),
]
app.get("/", (req, res) =>{
res.send("Hello Express")
});
app.get("/api/products", (req, res) =>{
let result = products;
let params = req.query;
if (params.title){
result = result.filter((p) => p.title.indexOf(params.title) !== -1);
}
if (params.price && result.length > 0){
result = result.filter((p) => p.price <= parseInt(params.price));
}
if (params.category && result.length >0){
result = result.filter((p) => p.categories.indexOf(params.category) !== -1)
}
res.json(result);
});
app.get("/api/product/:id", (req, res) =>{
res.json(products.find((product) => product.id == req.params.id))
});
app.get("/api/product/:id/comments", (req, res) =>{
res.json(comments.filter((comment: Comment) => comment.productId == req.params.id))
});
const server = app.listen(8000,"localhost", () =>{
console.log(":http://localhost:8000");
});
const subscriptions = new Map<any, number[]>();
const wsServer = new Server({port: 8085});
wsServer.on("connection", websocket =>{
websocket.send("");
websocket.on("message", message =>{
let messageObj = JSON.parse(message);
let productIds = subscriptions.get(websocket) || [];
subscriptions.set(websocket, [...productIds, messageObj.productId]);
});
});
const currentBids = new Map<number, number>();
setInterval(() =>{
products.forEach(p =>{
let currentBid = currentBids.get(p.id) || p.price;
let newBid = currentBid + Math.random()*5;
currentBids.set(p.id, newBid);
})
subscriptions.forEach((productIds: number[], ws) => {
if (ws.readyState === 1){
let newBids = productIds.map(pid => ({
productId: pid,
bid: currentBids.get(pid)
}));
ws.send(JSON.stringify(newBids));
}else {
subscriptions.delete(ws);
}
});
},2000);