问题描述
我在使用Angular搭建一个客户端,希望通过点击页面上的关注商品,就能从服务器获取实时更新的最新价格。可当我点击客户端按钮时,报出core.js:1633 ERROR SyntaxError: Unexpected token 这 in JSON at position 0的异常。浏览器调试错误如下:
已经困扰我两天了,网上能找到试的方法都试了,也解决不了。说是有可能是运用JSON转化客户端与服务器数据时JSON.stringify和JSON.parse的格式错误。可我还是找不出来啊,求大佬们帮帮忙。
相关代码
客户端
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>
<p>{{product?.desc}}</p>
</div>
<div>
<p class="pull-right">{{comments?.length}}</p>
<p>
<app-stars [rating]="product?.rating"></app-stars>
</p>
</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>
<p></p>
<p>{{comment.content}}</p>
</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));
}
}
服务器端
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);
解决了,忘了贴上来,这个