循环内的承诺:TypeScript + Angular + IndexedDB

Posted

技术标签:

【中文标题】循环内的承诺:TypeScript + Angular + IndexedDB【英文标题】:Promises within a loop: TypeScript + Angular + IndexedDB 【发布时间】:2015-09-09 15:14:14 【问题描述】:

我正在开发一项数据同步服务,该服务从 Web 服务中提取数据,然后将其存储在 IndexedDB 中。

我在我的 TypeScript Angular 服务中做这样的事情:

this.http
    .post(postUrl, postData)
    .success((data: any, status, headers, config) => 

         console.log("post success");
         console.log("results:");
         console.log(data);

         var records = data.Records;
         var promiseStack = [];

         for (var i = 0; i < records.length; i++) 

             var element = records[i];
             var key = this.dataService.getKeyFromElement(objectStoreConfig, element);

             console.log("key: " + key);

             this.dataService.keyExists(objectStoreConfig, key).then((update) => 

                 if(update)
                     // TODO: put
                     promiseStack.push(true);
                  else 
                     console.log("using dataService to add to objectStore...");
                     console.log("adding: " + key);
                     this.dataService.add(element, objectStoreConfig).then((result) => 
                         promiseStack.push(result);
                     );
                 
             );

         

         this.q.all(promiseStack).then((result) => 
             console.log("done adding/updating all.");
             deferred.resolve(result);
         );
    )
    .error((data, status, headers, config) => 
    );

我在控制台中收到一个post success,以及我预期的每个返回的record key。问题在于对我的DataService 的异步调用。 this.dataService.add 函数实际上是创建事务并将记录添加到 IndexedDb。

我的控制台中的输出(在 IndexedDB 的状态下 - 只有一条记录的键为 188)表明此代码示例在我的 @ 上调用了 add 函数987654329@ 表示records 中的最后一个元素。

控制台输出:

post success
results:
Object
key: 78 
key: 194
key: 188
done adding/updating all. 
using dataService to add to objectStore...
adding: 188
using dataService to add to objectStore...
adding: 188
using dataService to add to objectStore...
adding: 188  

如何以不同的方式构建我的代码以使 for 循环“等待”每个异步调用完成?

【问题讨论】:

【参考方案1】:

方法 1(仅适用于您的目标是 ES6)

如果您使用的是 TypeScript 1.5,您可以只使用 let 而不是 var 来声明您的元素和键变量:

let element = records[i];
let key = this.dataService.getKeyFromElement(objectStoreConfig, element);

问题是elementkey 在函数的范围内而不是for 循环,所以每次for 循环迭代它只是替换elementkey 变量而不是创建新变量。如果您使用let,那么变量将在 for 循环的范围内。

更多详情请见What's-new-in-TypeScript。

方法 2

或者,您也可以使用 Array.forEach 代替 for 循环,因为这也可以解决范围问题:

records.forEach(function(element) 
    //...
);

【讨论】:

注意:你不能在 for 循环中使用let,除非编译为 ES6。 对。这是有道理的。假设编译到 ES6 对我来说不是一个选项,还有其他方法可以解决范围问题吗? 你也可以在编译到 ES5 或 3 时使用它。引用我链接的 wiki 页面:“针对 ES3 和 ES5 时,现在支持 ES6 let 和 const 声明。” 除非它只适用于 if 语句而不适用于循环。但我没有看到任何提及 注意:使用 Array.forEach 代替 for 循环也可以解决问题...打赌 let 更酷

以上是关于循环内的承诺:TypeScript + Angular + IndexedDB的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript:返回一个承诺的结果

为啥 Typescript 认为 async/await 返回包装在承诺中的值?

在 TypeScript 中包装 Firebase 承诺

带有承诺返回错误的 Typescript onPress

Typescript 应用程序中的“mpromise(猫鼬的默认承诺库)已弃用”

关于用 Angular 和 typescript 链接 $q 承诺的困惑