第二次更新
我们正在实施 BulkEdit 功能,可将异步CRUD请求发送到后端。
所以我需要的是一个动态创建的嵌套承诺。
在抽象版本中,数据数组可能如下所示:
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: []
}
];
我尝试说明如何按照'_action'给出的顺序为这些数据发送请求。
只要有事务ID,就会开始根据以下规则发送对Array中每个Object的请求:
只要完成对Object的所有请求,就按对象执行操作。
如何创建此动态嵌套/非嵌套保证链?
更新后的代码 现在包含Promise Creation
当调用下面的函数时,首先TransactionService获取一个事务id,该事务id需要随每个请求一起发送。一切顺利后,交易将被关闭。
我当前的问题是Promises没有以正确的顺序解析(当OPTIONS预检请求似乎是这样)并且这个例子创建了Promises,即使它们不是必需的(例如上面例子中的Object'C')
function startIt(objArr) {
TransactionService.getTransaction().then(function (transaction) {
var promiseArray = MyService.submit(objArr, transaction.id);
$q.all(promiseArray).then(function () {
Transactions.closeTransaction(transaction.id, function () {}).then(function () {
});
};
});
}
这是'submit'的功能:
function submit(objArr, transactionId) {
var promises = objArr.map(function (obj) {
return submitWithTransId(transactionId, obj)
.then(function (response) {
// Object done
});
});
return promises;
}
这个函数实际上是在创建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'
}
}
);
答案 0 :(得分:3)
您可以查看以下解决方案。目标是为您提供某种结构。请注意,您必须修改您的使用。
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
}
请注意,上面的代码将执行以下操作
以下是plunker
的$q和文档<强>更新强>
问题在于createPromise
功能。将代码更新为以下内容。问题是你在返回之前调用了then
,因此,很可能你正在返回一个已解决的承诺,如$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;
}
答案 1 :(得分:1)
试试这个 - 诀窍是积累承诺(这就是我正在使用的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)
)
}))
答案 2 :(得分:1)
我很高兴和感恩,我找到了。
根据我的理解,我的代码中有两个主要问题。
由于$resource
没有提供(请原谅我,专业人士!)真实 $promise
即使我使用.get().$promise
之类的东西我也必须{ p>
bind
将 createPromise 功能映射到我的数组$q.all
承诺之前直接进行映射。在任何其他情况下,$resource
似乎立即用空对象填充其承诺,$q.all
不再起作用,因为承诺看起来像是在解决它们。
特别感谢@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);
});
});