Javascript Meteor 0.9.1.1-从json端点填充到服务器端集合
我正在编写一个包,作为我正在开发的一个小应用程序的一部分,我需要做的一件事是从端点获取json数据并将其填充到服务器端集合 我一直收到错误消息,告诉我需要将服务器端收集更新功能放入光纤或Meteor.bindEnvironment或Meteor.\u callAsync 我感到困惑,因为没有明确和简洁的解释告诉我它们到底做什么,它们是什么,它们是否被弃用以及何时被弃用,或者它们的使用是否是良好的实践 下面是我的包文件中的重要内容Javascript Meteor 0.9.1.1-从json端点填充到服务器端集合,javascript,node.js,meteor,fibers,Javascript,Node.js,Meteor,Fibers,我正在编写一个包,作为我正在开发的一个小应用程序的一部分,我需要做的一件事是从端点获取json数据并将其填充到服务器端集合 我一直收到错误消息,告诉我需要将服务器端收集更新功能放入光纤或Meteor.bindEnvironment或Meteor.\u callAsync 我感到困惑,因为没有明确和简洁的解释告诉我它们到底做什么,它们是什么,它们是否被弃用以及何时被弃用,或者它们的使用是否是良好的实践 下面是我的包文件中的重要内容 api.addFiles([ '_src/collecti
api.addFiles([
'_src/collections.js'
], 'server');
一点psuedo代码:
1) 设置Mongo.Collection项目的列表
2) 使用我编写的名为httpFetch()的函数填充这些集合,并对每个集合运行该函数,如果提取成功,则返回已解析的承诺
3) 在下划线each()循环中调用此httpFetch函数,遍历我拥有的每个集合,获取json数据,并尝试将其插入服务器端Mongo DB
Collections.js如下所示。在光纤中封装insert函数似乎可以抑制错误消息,但没有数据插入到数据库中
/**
*服务器端组件向远程服务器发出请求
*用于填充服务器端Mongo集合的端点。
*
*@class服务器
*@静态
*/
服务器={
Fiber: Npm.require('fibers'),
/**
* Collections to be populated with content
*
* @property Collections
* @type {Object}
*/
Collections: {
staticContent: new Mongo.Collection('staticContent'),
pages: new Mongo.Collection('pages'),
projects: new Mongo.Collection('projects'),
categories: new Mongo.Collection('categories'),
formations: new Mongo.Collection('formations')
},
/**
* Server side base url for making HTTP calls
*
* @property baseURL
* @type {String}
*/
baseURL: 'http://localhost:3000',
/**
* Function to update all server side collections
*
* @method updateCollections()
* @return {Object} - a resolved or rejected promise
*/
updateCollections: function() {
var deferred = Q.defer(),
self = this,
url = '',
collectionsUpdated = 0;
_.each(self.Collections, function(collection) {
// collection.remove();
url = self.baseURL + '/content/' + collection._name + '.json';
self.httpFetch(url).then(function(result) {
jsonData = EJSON.parse(result.data);
_.each(jsonData.items, function(item) {
console.log('inserting item with id ', item.id);
self.Fiber(function() {
collection.update({testID: "Some random data"}
});
});
deferred.resolve({
status: 'ok',
message: 'Collection updated from url: ' + url
});
}).fail(function(error) {
return deferred.reject({
status: 'error',
message: 'Could not update collection: ' + collection._name,
data: error
});
});
});
return deferred.promise;
},
/**
* Function to load an endpoint from a given url
*
* @method httpFetch()
* @param {String} url
* @return {Object} - A resolved promise if the data was
* received or a rejected promise.
*/
httpFetch: function(url) {
var deferred = Q.defer();
HTTP.call(
'GET',
url,
function(error, result) {
if(error) {
deferred.reject({
status: 'error',
data: error
});
}
else {
deferred.resolve({
status: 'ok',
data: result.content
});
}
}
);
return deferred.promise;
}
})
我仍然被这个问题困扰着,从我以前读过的其他帖子来看,我似乎仍然无法找到让它工作的“最佳实践”方法,或者根本无法让它工作
2011/2012年有很多建议,但我不愿意使用它们,因为Meteor处于不断变化之中,即使是一个小小的更新也会破坏很多东西
谢谢好消息:这个解决方案实际上比您目前编写的所有代码都要简单得多 根据我所掌握的,您编写了一个
httpFetch
函数,该函数使用异步版本的HTTP.get
来修饰承诺。然后,您尝试在新的光纤中运行集合更新,因为asyncHTTP.get
调用引入了一个回调,通过使用promiseThen
继续
首先,您需要使用服务器上提供的同步版本的HTTP.get
,这将允许您编写此类代码:
updateCollections:function(){
// we are inside a Meteor.method so this code is running inside its own Fiber
_.each(self.Collections, function(collection) {
var url=// whatever
// sync HTTP.get : we get the result right away (from a
// code writing perspective)
var result=HTTP.get(url);
// we got our result and we are still in the method Fiber : we can now
// safely call collection.update without the need to worry about Fiber stuff
});
您应该仔细阅读有关HTTP模块的文档:我现在有了这个功能。问题似乎是我的httpFetch函数返回了一个承诺,这导致了错误:
“错误:Meteor代码必须始终在光纤中运行。请尝试使用Meteor.bindEnvironment包装传递给非Meteor库的回调。”
我更改了这个httpFetch函数,以便在HTTP.get()调用成功或错误时运行回调
在这个回调函数中,是解析获取的数据并将其插入我的集合的代码,这是现在工作的关键部分
下面是修改后的Collections.js文件,其中包含解释一切的注释
Server = {
/**
* Collections to be populated with content
*
* @property Collections
* @type {Object}
*/
Collections: {
staticContent: new Mongo.Collection('staticContent'),
pages: new Mongo.Collection('pages'),
projects: new Mongo.Collection('projects'),
categories: new Mongo.Collection('categories'),
formations: new Mongo.Collection('formations')
},
/**
* Server side base url for making HTTP calls
*
* @property baseURL
* @type {String}
*/
baseURL: 'http://localhost:3000',
/**
* Function to update all server side collections
*
* @method updateCollections()
* @return {Object} - a resolved or rejected promise
*/
updateCollections: function() {
var deferred = Q.defer(),
self = this,
collectionsUpdated = 0;
/**
* Loop through each collection, fetching its data from the json
* endpoint.
*/
_.each(self.Collections, function(collection) {
/**
* Clear out old collection data
*/
collection.remove({});
/**
* URL endpoint containing json data. Note the name of the collection
* is also the name of the json file. They need to match.
*/
var url = self.baseURL + '/content/' + collection._name + '.json';
/**
* Make Meteor HTTP Get using the function below.
*/
self.httpFetch(url, function(err, res) {
if(err) {
/**
* Reject promise if there was an error
*/
deferred.reject({
status: 'error',
message: 'Error fetching content for url ' + url,
data: err
});
}
else {
/**
* Populate fetched data from json endpoint
*/
var jsonData = res.content;
data = EJSON.parse(res.content);
/**
* Pick out and insert each item into its collection
*/
_.each(data.items, function(item) {
collection.insert(item);
});
collectionsUpdated++;
}
if(collectionsUpdated === _.size(self.Collections)) {
/**
* When we have updated all collections, resovle the promise
*/
deferred.resolve({
status: 'ok',
message: 'All collections updated',
data: {
collections: self.Collections,
count: collectionsUpdated
}
});
}
});
});
/**
* Return the promise
*/
return deferred.promise;
},
/**
* Function to load an endpoint from a given url
*
* @method httpFetch()
* @param {String} url
* @param {Function} cb - Callback in the event of an error
* @return undefined
*/
httpFetch: function(url, cb) {
var res = HTTP.get(
url,
function(error, result) {
cb(error, result);
}
);
}
})