我遇到需要执行依赖异步操作的情况。例如,检查数据库中的数据,如果有数据,则执行数据库写入(插入/更新),如果不继续而不执行任何操作。我使用promise-as3编写了一个基于promise的数据库API。任何数据库操作都会返回使用读取查询的数据或写入查询的Result对象解析的promise。我执行以下操作来嵌套承诺,并为整个'初始化'创建一个解决方案或拒绝点。操作
public function initializeTable():Promise
{
var dfd:Deferred = new Deferred();
select("SELECT * FROM table").then(tableDefaults).then(resolveDeferred(dfd)).otherwise(errorHandler(dfd));
return dfd.promise;
}
public function tableDefaults(data:Array):Promise
{
if(!data || !data.length)
{
//defaultParams is an Object of table default fields/values.
return insert("table", defaultParams);
} else
{
var resolved:Deferred = new Deferred();
resolved.resolve(null);
return resolved.promise;
}
}
public function resolveDeferred(deferred:Deferred):Function
{
return function resolver(value:*=null):void
{
deferred.resolve(value);
}
}
public function rejectDeferred(deferred:Deferred):Function
{
return function rejector(reason:*=null):void
{
deferred.reject(reason);
}
}
我的主要问题:
修改 我正在删除问题3(有没有更好的方法来做到这一点?),因为它似乎引发了对异步编程中承诺性质的看法。我的承诺范围更好,而不是一般的异步性。假设您必须使用此基于承诺的API来解决问题。
答案 0 :(得分:1)
我通常不会写出那种基于意见的答案,但这里非常重要。 AS3中的承诺= 所有恶意的根源 :)我会解释你为什么......
首先,正如博特马斯特所说 - 它是弱类型的。这意味着你没有正确使用AS3。这是可能的唯一原因是因为向后兼容性。这里的真实情况是,Adobe花费了数千次,因此他们可以将AS3转换为强类型OOP语言。不要偏离它。
第二点是Promises,首先是创建的,这样可怜的开发人员实际上可以开始在JavaScript中做一些工作。这不是一种新的设计模式或其他东西。实际上,如果您知道如何正确构建代码,那么它没有任何实际好处。 Promises最有帮助的是避免所谓的Wall of Hell。但还有其他方法可以自然地解决这个问题(非常基本的不是在函数内编写函数,而是在同一级别上,只需检查传递的结果)。
这里的最重要的是Promises的本质。很少有人知道他们在幕后真正做了什么。由于JavaScript的本质(以及ECMA脚本),没有真正的方法来判断函数是否正确完成。如果您返回false
/ null
/ undefined
- 它们都是常规返回值。他们真正说出的唯一方法就是这个操作失败了#34;是通过抛出错误。所以每一个有效的方法都可能引发错误。每个错误必须处理,否则您的代码可能会停止正常工作。这意味着, Promise中的每一个动作都在try-catch块中!每次你做绝对基本的东西,你把它包装在try-catch中。即便是你的这块:
else
{
var resolved:Deferred = new Deferred();
resolved.resolve(null);
return resolved.promise;
}
在"常规"方式,你只需使用else { return null }
。但是现在,你创建了大量的对象,解析器,拒绝器,最后 - 你试着抓住这个块。
我不能再强调这一点,但我认为你明白了。 尝试捕捉非常慢!我知道这在我刚刚提到的这样一个简单的情况下不是一个大问题,但想象一下你做的更多,而且更重的方法。你只是做了极其缓慢的操作,为了什么?因为你可以编写蹩脚的代码而只是享受它..
最后要说的是 - 有很多很多方法可以使用异步操作并让它们一个接一个地工作。只是通过谷歌搜索as3 function queue
我发现了一些。并不是说基于事件的系统是如此灵活,甚至还有替代方案(使用回调)。你已经掌握了所有这些,并且你转向了创建的东西,因为缺乏正确的方法来实现它。
因此,作为一个与Flash合作十年,在大型团队中进行赌场游戏的人,我真诚的建议是 - 不要尝试在AS3中使用承诺。祝你好运!
答案 1 :(得分:0)
var dfd:Deferred = new Deferred();
select("SELECT * FROM table").then(tableDefaults).then(resolveDeferred(dfd)).otherwise(errorHandler(dfd));
return dfd.promise;
这是The Forgotten Promise反模式。它可以写成:
return select("SELECT * FROM table").then(tableDefaults);
这消除了对resolveDeferred
和rejectDeferred
功能的需求。
var resolved:Deferred = new Deferred();
resolved.resolve(null);
return resolved.promise;
我要将其提取到另一个函数,或者使用Promise.when(null)
。全局实例不起作用,因为它意味着可以调用来自一个调用的结果处理程序,而不是一个调用。