我试图用Javascript最好的实践,但对我来说这很难。在这种情况下,我想使用一些功能"避免"回调。我试图使用jquery的Deferred对象来做到这一点。所以我相信我不知道如何正常工作。
我正在使用 phonegap + emberjs + cordova-sqlite-plugin 。
我实现了回调的后续功能。
getPuntos: function(callback)
{
var db = window.sqlitePlugin.openDatabase("Rondas", "1.0", "Dev", -1);
var ret ={data:false};
db.transaction(function(tx)
{
tx.executeSql("SELECT * from Punto;",[], function(tx, res)
{
if( res.rows.length !== 0)
{
var puntos = [];
for( var i=0; i<res.rows.length; i++)
{
var descripcion = res.rows.item(i).descripcion;
var id = res.rows.item(i).id;
//console.log( descripcion );
var punto = App.Punto.create( { index: i, id:id, descripcion: descripcion});
puntos.push( punto );
}
ret.data = puntos;
callback(ret.data);
}
});
},function(tx,err){
console.log('Error SQL'+err);
},function(){
console.log( 'Base de datos abierta' );
});
}
我也使用它:
this.getPuntos(function(puntos){
for( var i=0; i<puntos.length; i++){
console.log( puntos[i] );
}
});
好吧,但我尝试实现一些非常简单明了的东西:
//whitout use a callback.
var puntos = this.getPuntos();
for( var i=0; i<puntos.length; i++){
console.log( puntos[i] );
}
然后我尝试这样做:
getPuntos
更改为_getPuntos
,此函数具有延迟的对象。 getPuntos
是包装器,用于处理方法_getPuntos
中的promise的结果并尝试返回。(但不起作用)_getPuntos: function()
{
var db = window.sqlitePlugin.openDatabase("Rondas", "1.0", "Dev", -1);
var deferred = jQuery.Deferred();
var ret ={data:false};
db.transaction(function(tx)
{
tx.executeSql("SELECT * from Punto;",[], function(tx, res)
{
if( res.rows.length !== 0)
{
var puntos = [];
for( var i=0; i<res.rows.length; i++)
{
var descripcion = res.rows.item(i).descripcion;
var id = res.rows.item(i).id;
//console.log( descripcion );
var punto = App.Punto.create( { index: i, id:id, descripcion: descripcion});
puntos.push( punto );
}
//ret.data = puntos;
//callback(ret.data);
deferred.resolve(puntos);
}
});
},function(tx,err){
console.log('Error SQL'+err);
},function(){
console.log( 'Base de datos abierta' );
});
return deferred.promise();
},
包装器:
getPuntos: function()
{
var promise = this._getPuntos();
var ret = {data:false};
promise.done(function(result)
{
ret.data = result;
return ret.data;
});
while(ret.data ===false ){} //wait for the result until it's available
return ret.data;
},
在主要功能中我称之为:
var puntos = this.getPuntos();
console.log( puntos+"--shoulbe [object]"); //I get Undefined or false, but no my array.
那么,有没有办法做到这一点我想要同步转换异步函数 功能?
感谢您的所有答案。
答案 0 :(得分:2)
这里的主要问题是第二个示例中的getPuntos()函数不返回任何内容,因此返回null / false值。
getPuntos: function()
{
var promise = this._getPuntos();
var ret = {data:false};
promise.done(function(result)
{
// This happens in the future
ret.data = result;
return ret.data;
});
// This happens now and there is nothing returned
},
当你的诺言完成后(promise.done),它会返回ret.data,但会返回到promise并被忽略。它的范围是错误的。你在思考传统的“拉动”。模型,数据被拉向您,程序阻塞,直到数据可用。 Javascript使用回调功能,而且更像是一种推送功能。模型,当数据可用且没有阻塞时,数据被推送到回调函数。
你需要重新安排事情。例如,getPuntos函数应返回promise。
getPuntos: function()
{
var promise = this._getPuntos();
return promise;
},
主要功能应该在履行承诺时添加回调。
var puntos = this.getPuntos();
puntos.done(function(result) {
console.log( result+"--shoulbe [object]");
});
尽管getPuntos()函数在这里有点多余,因为它只返回_getPuntos()的值。
答案 1 :(得分:1)
问题是您的getPuntos()
函数设置了promise.done
操作,但返回的值永远不会传递给您的程序的其余部分。正如NoxHarmonium所说,您的getPuntos()
方法是多余的,应与_getPuntos()
结合使用,但您可能需要以下内容(正如您在 this jsFiddle中看到的那样):
PuntosPromise = function() {
this.result = null;
this._getPuntos = function() {
var deferred = $.Deferred();
setTimeout(function(scope) {
scope.result = "It works."
deferred.resolve();
}, 500, this);
return deferred.promise();
}
this.getPuntos = function()
{
var promise = this._getPuntos();
return promise;
}
this.getResults = function() {
return this.result;
};
}
$("#tester").click(function() {
var test = new PuntosPromise();
$.when(test.getPuntos()).then(function() {
alert(test.getResults());
});
});
编辑:
请参阅下面给出的@ Bergi的修改。虽然这段代码有效,但他的解决方案更清晰。