我知道网上有很多很好的例子,我读过很多很好的例子,但是目前我还是坚持用nodejs 0.11.x中的生成器的新功能来解决承诺。
例如我有以下功能:
SolrBaseDomain.prototype.promisedQuery = function(query, callback) {
var solrClient = solr.createClient(this.configuration);
var defer = Q.defer();
solrClient.search(query, function(err,obj){
if (!err) {
if (obj.response.numFound > 0) {
defer.resolve(obj.response.docs);
} else {
defer.resolve(null);
}
} else {
defer.reject(err);
}
});
var promise = defer.promise;
return Q.async(function* (){
var result = yield promise;
return result;
});
};
我希望每次对这个方法的调用都会等到promise被完全填充,并且return语句会返回promise的结果。
但是目前似乎代替里面的代码" Q.async ......"执行方法的return语句后,将不会执行或异步调用到达。
很奇怪,在我知道的每个例子中,这是等待nodejs中的异步调用的推荐方法之一,但目前它对我不起作用。
我已尝试过上述示例的许多不同变体,但结果是每次都相同,我得不到有效的结果。
我在版本0.11.10中安装了nodejs,并且当代码为execute时设置了 - harmony -flag。
有人能指出我正确的方向吗?我想知道我是否监督某事...... :)
感谢您的反馈。
祝你好运
Udo
答案 0 :(得分:0)
试试这个
SolrBaseDomain.prototype.promisedQuery = Q.async(function*(query) {
var solrClient = solr.createClient(this.configuration);
var obj = yield Q.ninvoke(solrClient, "search", query);
return obj.response.numFound > 0 ? obj.response.docs : null;
});
对于promises,这与回调相同:
SolrBaseDomain.prototype.query = function (query, callback) {
var solrClient = solr.createClient(this.configuration);
solrClient.search(query, function(err, obj) {
if (err) return callback(err);
callback(null, obj.response.numFound > 0 ? obj.response.docs : null);
});
};
因此,如果第一个返回一个解析为undefined的promise,那么回调版本将使用undefined调用回调。
答案 1 :(得分:0)
我希望每次对这个方法的调用都会等到promise被完全填充,并且return语句会返回promise的结果。
没有。生成器不会使函数同步,您不能(并且不想)在等待结果时阻塞。当调用生成器函数并按顺序运行它产生的异步步骤时,最终返回的结果仍然是异步的 - 因此是一个承诺。只有生成器中的 ,您的代码才能使用同步控制流和yield
。
这意味着(then
- )基于回调的代码
SolrBaseDomain.prototype.promisedQuery = function(query) {
var promise = Q.ninvoke(solr.createClient(this.configuration), "search", query);
return promise.then(function(obj) {
if (obj.response.numFound > 0) {
return obj.response.docs;
} else {
return null;
}
});
};
变为
SolrBaseDomain.prototype.promisedQuery = Q.async(function* (query) {
var promise = Q.ninvoke(solr.createClient(this.configuration), "search", query);
var obj = yield promise;
// ^^^^^
if (obj.response.numFound > 0) {
return obj.response.docs;
} else {
return null;
}
});
答案 2 :(得分:0)
根据您的建议,我的代码现在看起来像这样:
...
SolrBaseDomain.prototype.query = Q.async(function* (query) {
var solrClient = solr.createClient(this.configuration);
var obj = yield Q.ninvoke(solrClient, "search", query);
return obj.response.numFound > 0 ? obj.response.docs : null;
});
...
我在所有数据访问层上共享上述查询功能,以便有一个以异步方式查询不同索引的中心方法。
例如在域数据访问层中,处理该函数的代码如下所示:
SolrHostDomain.prototype.getByName = Q.async(function* (domain) {
var queryObject = {
"domain": domain
};
var query = this.getQuery("byName", queryObject);
var docs = yield this.query(query);
var domain = null;
if (docs != null && docs.length > 0) {
domain = this.dataMapper.merge(docs[0]);
}
return domain;});
目前我不确定“getByName”函数中的生成器是否必要,但它似乎有效。处理承诺对我来说是一个不明确的概念,因为我是nodejs的新手。
所以,也许,如果你可以帮我解决这个话题,并指出我正确的方向,这将是有帮助的。
对我来说,主要的问题是,我怎样才能确保同步方法可以调用异步方法并返回不是承诺,而是这个承诺的最终结果。
我已经搜索了很长时间,但是我找不到一个很好的文档来描述生成器函数或promises与同步调用的结合使用。甚至示例都只关注使用机制但不与同步函数一起工作。
致以最诚挚的问候,非常感谢您的帮助
乌
答案 3 :(得分:0)
得到了!!!
经过一些试验和错误后,我想我现在得到了它,并且我有一个有效的解决方案:
查询功能:
SolrBaseDomain.prototype.query = Q.async(function* (query) {
var solrClient = solr.createClient(this.configuration);
var obj = yield Q.ninvoke(solrClient, "search", query);
return obj.response.numFound > 0 ? obj.response.docs : null;
});
通话方式:
SolrHostDomain.prototype.getByName = function(domain) {
var queryObject = {
"domain": domain
};
var query = this.getQuery("byName", queryObject);
var docsPromise = this.query(query);
var _self = this;
return docsPromise.then(function(docs) {
var domain = null;
if (docs != null && docs.length > 0) {
domain = _self.dataMapper.merge(docs[0]);
}
return domain;
});
};
解决方案是要明白,即使使用了yield,“query”-method仍然会返回一个promise而不是具体的结果。
所以我必须在“then”函数中添加正在处理promise的结果的每个代码(如果在方法的调用层次结构中没有其他调用者将跟随,则“完成”)。
在解除承诺后,将处理在“then”功能中设置的每个代码。
BR
乌