在ActionScript中嵌套异步Promise

时间:2015-06-09 16:16:06

标签: actionscript-3 asynchronous promise

我遇到需要执行依赖异步操作的情况。例如,检查数据库中的数据,如果有数据,则执行数据库写入(插入/更新),如果不继续而不执行任何操作。我使用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);
    }
}

我的主要问题:

  1. 这会产生任何性能问题吗?内存泄漏等?我已经读过功能变量表现不佳,但我没有看到另外一种逻辑嵌套操作的方法。
  2. 最好是说一个全局解析的实例只创建并解析一次,但只要我们需要一个空的'就会返回。保证?
  3. 修改 我正在删除问题3(有没有更好的方法来做到这一点?),因为它似乎引发了对异步编程中承诺性质的看法。我的承诺范围更好,而不是一般的异步性。假设您必须使用此基于承诺的API来解决问题。

2 个答案:

答案 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);

这消除了对resolveDeferredrejectDeferred功能的需求。

var resolved:Deferred = new Deferred();
resolved.resolve(null);
return resolved.promise;

我要将其提取到另一个函数,或者使用Promise.when(null)。全局实例不起作用,因为它意味着可以调用来自一个调用的结果处理程序,而不是一个调用。