Angularjs 动态嵌套的$resource承诺与有序的$q.all承诺
第二次更新 我们正在实现一个BulkEdit功能,它向后端发送异步CRUD请求 因此,我在这里需要的是一组动态创建的嵌套承诺 在抽象版本中,数据数组可能如下所示:Angularjs 动态嵌套的$resource承诺与有序的$q.all承诺,angularjs,angular-promise,Angularjs,Angular Promise,第二次更新 我们正在实现一个BulkEdit功能,它向后端发送异步CRUD请求 因此,我在这里需要的是一组动态创建的嵌套承诺 在抽象版本中,数据数组可能如下所示: var objArr = [ { name: 'A', subs: [ { id: 1, _action: 'create' }, { id: 2, _action: '
var objArr = [
{
name: 'A',
subs: [
{
id: 1,
_action: 'create'
},
{
id: 2,
_action: 'create'
},
{
id: 3,
_action: 'delete'
}
]
},
{
name: 'B',
subs: [
{
id: 4,
_action: 'create'
},
{
id: 5,
_action: 'put'
}
]
},
{
name: 'C',
subs: []
}
];
我试图说明应该如何按照“\u action”给出的顺序发送对该数据的请求
- 每个对象一次发送所有“删除”请求(如果有)
- 之后,或者如果没有任何“删除”请求,则发送所有“放置” 如果有的话,请求
- 在“删除”和/或“放置”之后,发送所有“创建”请求(如果有)
function submit(objArr, transactionId) {
var promises = objArr.map(function (obj) {
return submitWithTransId(transactionId, obj)
.then(function (response) {
// Object done
});
});
return promises;
}
这个功能实际上是在创造承诺:
function submitWithTransId(transactionId, obj) {
var promisesDelete = [];
var promisesUpdate = [];
var promisesCreate = [];
angular.forEach(obj['subs'], function (sub) {
switch (sub._action) {
case 'delete':
promisesDelete.push(createPromise(sub, bulktransactionId));
break;
case 'put':
promisesUpdate.push(createPromise(sub, bulktransactionId));
break;
case 'create':
promisesCreate.push(createPromise(sub, bulktransactionId));
break;
}
});
var chainedPromises = $q.all(promisesDelete).then(function (deleteResponse) {
return $q.all(promisesUpdate).then(function (updateResponse) {
return $q.all(promisesCreate).then(function (createResponse) {
});
});
});
return chainedPromises;
这是我的createPromise
函数:
/** only simplified handling create case **/
function createPromise(sub, bulktransactionId) {
var queryParams = {};
if (bulktransactionId !== undefined && bulktransactionId !== null) {
queryParams.transaction_id = bulktransactionId;
}
var promise = MyResourceService.create(queryParams, sub).$promise;
promise.then(function (newSub) {
// do something with the new/updated/deleted sub, especially update view model
});
return promise;
}
/** MyResourceService **/
return $resource(ENV.apiEndpoint + 'api/v1/subs/:_id',
{
_id: '@id'
}, {
create: {
method: 'POST'
}
}
);
您可以看看下面的解决方案。目的是为您提供某种结构。请看,您将不得不修改您的使用
var objArr = [{
name: 'A',
subs: [{
id: 1,
_action: 'create'
},
{
id: 2,
_action: 'create'
},
{
id: 3,
_action: 'delete'
}
]
},
{
name: 'B',
subs: [{
id: 4,
_action: 'create'
},
{
id: 5,
_action: 'put'
}
]
},
{
name: 'C',
subs: []
}
];
var promises = objArr.map(function(obj) {
return firstLevelPromise(obj)
.then(function(response) {
console.log(response); // promise for each object
return response;
});
});
$q.all(promises)
.then(function(response) {
console.log(response); // completion - close transaction
});
function firstLevelPromise(obj) {
var deletePromises = [];
var putPromies = [];
var insertPromies = [];
obj.subs.forEach(function(sub) { // Preparing promises array for delete, put and insert
if (sub._action === "delete") {
deletePromises.push(deletePromise(sub));
} else if (sub._action === "put") {
putPromies.push(putPromise(sub));
} else {
insertPromies.push(insertPromise(sub));
}
});
return $q.all(deletePromises) // executing delete promises
.then(function(deleteResponse) {
console.log("deleteExecuted: " + obj.name);
return $q.all(putPromies) // on completion of delete, execute put promies
.then(function(putResponse) {
console.log("putExecuted: " + obj.name);
return $q.all(insertPromies) // on completion of put, execute insert promises
.then(function(insertResponse) {
console.log("insertExecuted: " + obj.name);
return "object promise completed: " + obj.name; // on completion, return
});
});
});
}
function deletePromise(task) {
return $q.resolve(task); // write your delete code here
}
function putPromise(task) {
return $q.resolve(task); // write your put code here
}
function insertPromise(task) {
return $q.resolve(task); // write your insert code here
}
请注意,上述代码将执行以下操作
- 准备承诺集合,其中objectArray中的每个对象都有一个承诺
- 每个承诺都有一个承诺链,即删除承诺,然后是put承诺,最后是insert承诺,即它确保每个对象执行删除任务,然后在完成时执行put任务,然后在完成时执行insert任务
createPromise
函数。将代码更新为以下内容。问题是您在返回之前调用了,然后调用了,因此,您很可能返回了一个已解决的承诺,如$q.resolve()
。在这种情况下,create
请求可能在delete
或put
之前得到解决,而put
调用可能在delete
之前得到解决。因此,您应该从这里返回承诺,并在$q.all
块中执行操作后的操作
function createPromise(sub, bulktransactionId) {
var queryParams = {};
if (bulktransactionId !== undefined && bulktransactionId !== null) {
queryParams.transaction_id = bulktransactionId;
}
return MyResourceService.create(queryParams, sub).$promise;
}
试试这个-诀窍是累积承诺(这就是我使用reduce
的目的。希望它能有所帮助
// reversed the order => delete actions first; otherwise you may have to do extra logic may be needed
var objArr = [
{ name: 'A',
subs: [
{ id: null,
_action: 'delete'
},
{ id: 2,
_action: 'create']
}
},
{ name: 'B',
subs: [
{ id: 3.
_action: 'create'
}
]
];
Promise.all(objArr.map(obj => {
return obj.subs.reduce((accumulatedPromisedSub, sub) => {
return accumulatedPromisedSub.then(_ => yourRequestCallHere(sub) )
},
Promise.resolve(true) // you could also do your delete here if you like
)
}))
// OR going sort order agnostic:
Promise.all(objArr.map(obj => {
const deleteAction = obj.subs.find(sub => sub._action === 'delete');
return obj.subs.reduce((accumulatedPromisedSub, sub) => {
if (sub._action === 'delete') return accumulatedPromisedSub;
return accumulatedPromisedSub.then(_ => yourRequestCallHere(sub) )
},
deleteAction ? yourRequestCall(deleteAction) : Promise.resolve(true)
)
}))
我很高兴也很感激,我找到了它
据我所知,我的代码中有两个主要问题
因为$resource
没有提供(请原谅我,专业人士!)真实的$promise
即使我使用类似.get()。$promise
的东西,我也不得不这样做
使用bind
将createPromise函数映射到我的数组
仅在返回$q.all
承诺之前直接进行映射
在任何其他情况下,$resource
似乎立即用一个空对象来填充它的承诺,$q。所有的
都不再有效,因为承诺看起来像是解决了问题
特别感谢@nikhil,他支持我找到了这个丑陋复杂的东西,并赢得了赏金
这是工作片段:
function submitWithTransId(transactionId, obj) {
var arrayDelete = [];
var arrayUpdate = [];
var arrayCreate = [];
angular.forEach(obj['subs'], function (sub) {
switch (sub._action) {
case 'delete':
arrayDelete.push(sub);
break;
case 'update':
arrayUpdate.push(sub);
break;
case 'create':
arrayCreate.push(sub);
break;
}
});
var promisesDelete = flattenArray(arrayDelete.map(createPromise.bind(undefined, obj, transactionId)));
return $q.all(promisesDelete).then(function (deleteResponse) {
console.log('Delete Promises ' + obj.name + ' resolved');
var promisesUpdate = flattenArray(arrayUpdate.map(createPromise.bind(undefined, obj, transactionId)));
return $q.all(promisesUpdate).then(function (updateResponse) {
var promisesCreate = flattenArray(arrayCreate.map(createPromise.bind(undefined, obj, transactionId)));
console.log('Update Promises ' + obj.name + ' resolved');
return $q.all(promisesCreate).then(function (createResponse) {
console.log('Create Promises ' + obj.name + ' resolved');
});
});
}).catch(function (error) {
console.log('Catched an error: ');
console.log(error);
});
})) 你能把它分成两个数组,然后首先处理所有的删除,当所有的承诺都完成后,再处理其余的吗?也许可以构建两个承诺数组,一个用于创建,一个用于删除。然后你可以做一些像Promise.all(deletes).Then(function(){Promise.all(creates);}(是的,我可以这样做,但是它不是“每个对象”执行的,它是引导某个对象“一个”完成的过程:-(@LBA)你可以构建一个包含它们自己的承诺数组的对象数组。@BrianGlaz,你可能是对的,但这正是我作为一个主要使用PHP的人被卡住的地方:-(我真的在尝试理解并将其应用到我的代码中。目前没有任何成功。但我会进一步尝试。好的。如果你在某个地方遇到困难,请告诉我。谢谢,如果我正确理解了你的问题,你的解决方案是为每个“操作”创建承诺,而不是为每个“操作”创建每个“对象”,我会再次更新我的问题,尝试更加精确。@LBA)-那么它似乎是正确的,直到并且除非createPromise
函数中出现了一些问题。请您也添加createPromise
函数好吗?我同意@nikhil。OP用于填充promisesDelete
,promisesUpdate
的createPromise>函数肯定存在一些问题ndpromisesCreate
数组。另外,@LBA在调用它时如何引用bulktransactionId
?它不应该是transactionId
?
function submitWithTransId(transactionId, obj) {
var arrayDelete = [];
var arrayUpdate = [];
var arrayCreate = [];
angular.forEach(obj['subs'], function (sub) {
switch (sub._action) {
case 'delete':
arrayDelete.push(sub);
break;
case 'update':
arrayUpdate.push(sub);
break;
case 'create':
arrayCreate.push(sub);
break;
}
});
var promisesDelete = flattenArray(arrayDelete.map(createPromise.bind(undefined, obj, transactionId)));
return $q.all(promisesDelete).then(function (deleteResponse) {
console.log('Delete Promises ' + obj.name + ' resolved');
var promisesUpdate = flattenArray(arrayUpdate.map(createPromise.bind(undefined, obj, transactionId)));
return $q.all(promisesUpdate).then(function (updateResponse) {
var promisesCreate = flattenArray(arrayCreate.map(createPromise.bind(undefined, obj, transactionId)));
console.log('Update Promises ' + obj.name + ' resolved');
return $q.all(promisesCreate).then(function (createResponse) {
console.log('Create Promises ' + obj.name + ' resolved');
});
});
}).catch(function (error) {
console.log('Catched an error: ');
console.log(error);
});