目前我能够优化性能,但仍然有点慢:/
最新编辑:
我目前的解决方案(最快的atm(但仍然很慢)并保持秩序):
服务器
router.post('/images', function(req, res, next) {
var image = bucket.file(req.body.image);
image.download(function(err, contents) {
if (err) {
console.log(err);
} else {
var resultImage = base64_encode(contents);
var index = req.body.index;
var returnObject = {
image: resultImage,
index: index
}
res.send(returnObject);
}
});
});
客户查询
$scope.getDataset = function() {
fb.orderByChild('id').startAt(_start).limitToFirst(_n).once("value", function(dataSnapshot) {
dataSnapshot.forEach(function(childDataSnapshot) {
_start = childDataSnapshot.child("id").val() + 1;
var post = childDataSnapshot.val();
var image = post.image;
var imageObject = {
image: image,
index: position
};
position++;
$.ajax({
type: "POST",
url: "images",
data: imageObject,
}).done(function(result) {
post.image = result.image;
$scope.data[result.index] = post;
$scope.$apply();
firstElementsLoaded = true;
});
})
});
};
客户端HTML
<div ng-controller="ctrl">
<div class="allcontent">
<div id="pageContent" ng-repeat="d in data track by $index"><a href="details/{{d.key}}" target="_blank"><h3 class="text-left">{{d.title}}<a href="../users/{{d.author}}"><span class="authorLegend"><i> by {{d.username}}</i></span></a></h3>
</a>
<div class="postImgIndex" ng-show="{{d.upvotes - d.downvotes > -50}}">
<a href="details/{{d.key}}" target="_blank"><img class="imgIndex" ng-src="data:image/png;base64,{{d.image}}"></a>
</div>
<div class="postScore">{{d.upvotes - d.downvotes}} HP</div>
</div>
</div>
</div>
答案 0 :(得分:3)
您的解决方案很慢,因为您从云存储中下载图像并在自己的服务器上提供这些图像。下载和上传会延迟,使用base64编码数据会产生约33%的开销,而且您的服务器在提供图像方面也很紧张,而不是专注于提供网站内容。
正如许多评论所指出的那样,最佳实践解决方案是使用图像的公共URL,如下所示:
function getPublicUrl (filename) {
return "https://storage.googleapis.com/${CLOUD_BUCKET}/${filename}";
}
通过使用公开网址,您可以直接通过Cloud Storage 利用Google的全球服务基础架构提供服务。并且应用程序不必响应图像请求,从而为其他请求释放CPU周期。
如果您不希望机器人使用上述方法抓取您的图片,Google建议您使用robots.txt文件阻止访问您的图片。
答案 1 :(得分:1)
base64_encode(contents)
可能会耗费大量CPU,您的逻辑似乎反复这样做。这是猜测,你自己找到它的真正瓶颈优化数据收集 - 服务器端,哪个操作花费了太多时间
router.post('/images', function(req, res, next) {
var d = new Date()
var image = bucket.file(req.body.image);
image.download(function(err, contents) {
console.log('download:' + new Date() - d)
if (err) {
console.log(err);
} else {
var resultImage = base64_encode(contents);
console.log('base64_encode:' + new Date() - d)
var index = req.body.index;
var returnObject = {
image: resultImage,
index: index
}
res.send(returnObject);
}
});
});
&#13;
优化数据收集 - 客户端()
免除使用base64_encode(contents)
$scope.getDataset = function() {
fb.orderByChild('id').startAt(_start).limitToFirst(_n).once("value", function(dataSnapshot) {
dataSnapshot.forEach(function(childDataSnapshot, index) {
_start = childDataSnapshot.child("id").val() + 1;
var post = childDataSnapshot.val();
getImageBase64(post.image)
.then((image) => {
post.image = image;
$scope.data[index] = post;
$scope.$apply();
firstElementsLoaded = true;
})
})
});
function getImageBase64(image1) {
//without help of server, this will make your app faster
//network reduced
//server calculation reduced
if (CanIUseBucktAndBase64Here) {
return new Promise((reslove, reject) {
var image = bucket.file(image1);
image.download(function(err, contents) {
if (err) {
reject(err);
} else {
//use worker thread might gain better performance
var resultImage = base64_encode(contents);
resolve(resultImage)
}
});
})
}
//with help of server
return $.ajax({
type: "POST",
url: "images",
data: image1,
})
.then(result => result.image)
}
};
&#13;
每次都避免下载
//------------load all to local suit for less images----------
// if you have many images and you can use cheaper cache like file cache
//--init.js download all images, run only once
downloadAll()
//--server.js
//when image updated, let server know and flush cache
server.get('/imageupdated', (req, res) => {
downfile(req.params.imgid)
res.send('got it')
})
//form cache first
server.post('/image', (req, res) => {
memcache.get(req.body.imgid)
.then((content) => {
if (!content) return downfile(req.body.imgid)
res.send({
content
})
return true
})
.then((content) => {
if (content === true) return
res.send({
content
})
})
})
server.listen()
//--common.js download file and cache to memcache
function downfile(imgid) {
var base64 = ''
return bucket.download(imgid)
.then((file) => {
base64 = base64(file)
return memcache.set(imgid, base64)
})
.then(() => {
return base64
})
}
//downfileBatch
async function downfileBatch(skip, limit) {
return cloudDrive.getImages(skip, limit)
.then((list) => {
return Promise.all(list.map())
})
}
//down load all images
async function downloadAll() {
var i = 0,
limit = 5
while (true) {
var list = await downfileBatch(i, limit)
if (list.length < limit) {} else {
i += limit
}
}
return true
}
&#13;
答案 2 :(得分:-1)
优化代码的最简单方法是向服务器端发送单个ajax请求,而不是为每个映像执行ajax请求。
从循环中删除ajax调用。循环遍历集合,收集需要发送到阵列中的服务器的数据,然后通过单个ajax请求发送它。这会加快速度。
此外,请确保修改服务器端POST处理程序以便它可以处理数组,您将从客户端传递。
答案 3 :(得分:-2)
我不确定如何提高传送文件的速度,但是它们出现故障的问题是因为它们是异步的。基本上发生的事情是你告诉服务器给你一堆文件然后你等待。一旦服务器将它们发送给您,您就可以处理它们。但是你不知道他们进来的顺序。您需要做的是跟踪他们到达的顺序。这样做的方法是通过某种方式跟踪每个帖子的信息。 例如,假设你有
var arr = new Array(10);
for (var i = 0 ; i < arr.length; i++){
$.ajax({
url:____,
type:"GET" (or whatever type you want),
data: _____,
context: {index: i}
success : function(data){
arr[this.index] = data
}
})
}
这应该正确设置值。语法可能有点偏,但我相信这是以正确的顺序设置它们的正确想法。重要的是设置上下文,这将设置&#34;这个&#34;在成功处理程序中等于