angularJS 和 Typescript 的承诺
Promises with angularJS and Typescript
我有以下功能,我的目标是推送到项目列表,当组件可以识别它们的父项目时。
我遇到的问题是,当我推送到列表时 console.log() 显示对象在那里,但是当我 return 列表并在另一个函数中捕获它时,什么也没有在列表中。
我认为项目列表在上面的代码完成之前 returned。
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 [];
});
}
在第一个 promise 回调中,你有两个 returns,只有第一个运行。您 return 在第一个 for
之后做出承诺,您将其解析为 undefined
。您应该等待一系列承诺,每个承诺对应一个 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 [];
} )
如果您只想要一个项目,请在结果数组中找到第一个非 falsy 元素
恐怕问题出在你的方法上,而不是代码本身。承诺就是 - 未来某个时间的数据承诺。因此,当您执行 returns 函数(立即)时,promise 尚未解析,您的调用函数捕获的数据仍然为空。我在你的代码中没有看到 console.log(),但我怀疑你把它放在 then() 的某个地方,一旦收到数据就会调用它。所以你会看到数据被记录下来。问题是那个时候 get_items_for_request() 已经返回并且你的调用函数已经移动了。
如果你想使用一个承诺,你必须使用一个回调,一旦承诺被解决就被调用。但是,如果您希望将实际数据返回给调用者,则需要同步获取数据。
对于同步提取,检查this response。但要注意同步获取会损害脚本的响应能力。
对于异步获取(使用 promises),您需要定义一个回调,在获取所有数据后调用。我不会尝试修复您的代码,但它应该符合 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)
}
}
}
}
}
我有以下功能,我的目标是推送到项目列表,当组件可以识别它们的父项目时。 我遇到的问题是,当我推送到列表时 console.log() 显示对象在那里,但是当我 return 列表并在另一个函数中捕获它时,什么也没有在列表中。 我认为项目列表在上面的代码完成之前 returned。
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 [];
});
}
在第一个 promise 回调中,你有两个 returns,只有第一个运行。您 return 在第一个 for
之后做出承诺,您将其解析为 undefined
。您应该等待一系列承诺,每个承诺对应一个 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 [];
} )
如果您只想要一个项目,请在结果数组中找到第一个非 falsy 元素
恐怕问题出在你的方法上,而不是代码本身。承诺就是 - 未来某个时间的数据承诺。因此,当您执行 returns 函数(立即)时,promise 尚未解析,您的调用函数捕获的数据仍然为空。我在你的代码中没有看到 console.log(),但我怀疑你把它放在 then() 的某个地方,一旦收到数据就会调用它。所以你会看到数据被记录下来。问题是那个时候 get_items_for_request() 已经返回并且你的调用函数已经移动了。
如果你想使用一个承诺,你必须使用一个回调,一旦承诺被解决就被调用。但是,如果您希望将实际数据返回给调用者,则需要同步获取数据。
对于同步提取,检查this response。但要注意同步获取会损害脚本的响应能力。
对于异步获取(使用 promises),您需要定义一个回调,在获取所有数据后调用。我不会尝试修复您的代码,但它应该符合 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)
}
}
}
}
}