使用 angularJS 和 Typescript 的 Promise
Posted
技术标签:
【中文标题】使用 angularJS 和 Typescript 的 Promise【英文标题】:Promises with angularJS and Typescript 【发布时间】:2016-09-09 10:30:58 【问题描述】:我有以下功能,我的目标是在组件可以识别其父项时推送到项目列表。 我遇到的问题是,当我推送到列表时,console.log() 向我显示对象在其中,但是当我返回列表并在另一个函数中捕获它时,列表中没有任何内容。 我认为项目列表是在上面的代码完成之前返回的。
private get_items_for_request()
return this.Item.forRequest(this.request.id, ['group'])
.then((_items) =>
var items = [];
for (var item of _items)
return this.ItemComponent.forItem(item.id, ['type'])
.then((_components) =>
for (var component of _components)
if (component.type.can_identify_item)
items.push(
group_id: item.group.reference,
identifier_code: this.remove_check_digit_if_necessary(
component.identifier_code),
quantity: 1
);
break;
, (reason) =>
this.Toast.error(
this.gettextCatalog.getString('components.load_failed'));
return [];
);
return items;
, (reason) =>
this.Toast.error(
this.gettextCatalog.getString('items.failed_load'));
return [];
);
【问题讨论】:
【参考方案1】:恐怕问题出在您的方法上,而不是代码本身。一个承诺就是这样——一个未来某个时间数据的承诺。因此,当您的函数(立即)返回时,promise 尚未解决,并且您的调用者函数捕获的数据仍然是空的。我在您的代码中没有看到 console.log(),但怀疑您将它放在 then() 中的某个位置,一旦收到数据就会调用它。因此,您将看到正在记录的数据。麻烦的是到那时 get_items_for_request() 已经返回并且您的调用者函数已经继续。
如果你想使用一个promise,你必须在promise被解决后使用一个回调函数。但是,如果您希望将实际数据返回给调用者,则需要同步获取数据。
对于同步提取,请检查this response。但请注意,同步获取会损害脚本的响应能力。
对于异步获取(使用 Promise),您需要定义在获取所有数据后调用的回调。我不会尝试修复您的代码,但它应该遵循以下 javascript 草图。但请记住,这只是一个草图。
function get_items_for_request(onSuccess)
var items = []
var total = -1
var sofar = 0;
this.Item.forRequest(this.request.id, ['group'])
.then(function (_items)
var items = [];
total = _items.length // remember how many nested calls will be made
for (var item of _items)
this.ItemComponent.forItem(item.id, ['type'])
.then(function (_components)
// push received data to the items array here
sofar++
if (sofar == total) // all done
onSuccess(items)
【讨论】:
【参考方案2】:在第一个 promise 回调中,你有两个返回,只有第一个运行。你在第一个for
之后返回一个承诺,你将其解析为undefined
。您应该等待一组 promise,每个 promise 对应一个 this.ItemComponent.forItem
调用。
Promise.all
帮助解决这个问题:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
你应该这样做:
return this.Item.forRequest(this.request.id, ['group']).then((_items) =>
return Promise.all(_items.map(function (item)
return this.ItemComponent.forItem(item.id, ['type']).then((_components) =>
for (var component of _components)
if (component.type.can_identify_item)
return
group_id: item.group.reference,
identifier_code: this.remove_check_digit_if_necessary(
component.identifier_code),
quantity: 1
;
, (reason) =>
this.Toast.error(
this.gettextCatalog.getString('components.load_failed'));
return [];
);
));
, (reason) =>
this.Toast.error(
this.gettextCatalog.getString('items.failed_load'));
return [];
)
如果您只想要一个项目,请在结果数组中找到第一个非虚假元素
【讨论】:
@GiftZwergrapper 如果你想收到一个工作代码,你必须链接一个 plunkr 示例,或者至少是整个文件。我不知道你期待什么,我们不是媒介。如果你使用 Angular 1,$q
服务就是你的 Promise 库。
@GiftZwergrapper 也请注意,我指出的错误仍然存在,您在这里的反对意见有点激进。
在 Angular 中,您可以使用 $q.all
实现相同目的
$q.all 更好,因为它会触发摘要循环。 Promise.all 可能不会。以上是关于使用 angularJS 和 Typescript 的 Promise的主要内容,如果未能解决你的问题,请参考以下文章
使用 TypeScript 和注入的 AngularJS 过滤器
带有 ControllerAs 和 TypeScript 类的 AngularJs 指令
使用 angularJS 和 Typescript 的 Promise