* Implemented syncing afterSave/afterDelete trigger calls with REST request execution flow (Issue 2489). After this change, afterSave and afterDelete triggers CAN return a promise, which needs to be resolved inside a trigger for REST request flow to continue. If trigger doesn't return a promise, request flow continues.
* Added {} to multiline if.
* Fixed bad commit.
* Fixed problem with beforeSave triggers becoming async.
This commit is contained in:
committed by
Florent Vilmart
parent
430ae378f2
commit
3164b478ea
@@ -162,6 +162,162 @@ describe('Cloud Code', () => {
|
||||
}, 500);
|
||||
});
|
||||
|
||||
it('test afterSave ran on created object and returned a promise', function(done) {
|
||||
Parse.Cloud.afterSave('AfterSaveTest2', function(req) {
|
||||
let obj = req.object;
|
||||
if(!obj.existed())
|
||||
{
|
||||
let promise = new Parse.Promise();
|
||||
setTimeout(function(){
|
||||
obj.set('proof', obj.id);
|
||||
obj.save().then(function(){
|
||||
promise.resolve();
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
return promise;
|
||||
}
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('AfterSaveTest2');
|
||||
obj.save().then(function(){
|
||||
let query = new Parse.Query('AfterSaveTest2');
|
||||
query.equalTo('proof', obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results.length).toEqual(1);
|
||||
let savedObject = results[0];
|
||||
expect(savedObject.get('proof')).toEqual(obj.id);
|
||||
done();
|
||||
},
|
||||
function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('test afterSave ignoring promise, object not found', function(done) {
|
||||
Parse.Cloud.afterSave('AfterSaveTest2', function(req) {
|
||||
let obj = req.object;
|
||||
if(!obj.existed())
|
||||
{
|
||||
let promise = new Parse.Promise();
|
||||
setTimeout(function(){
|
||||
obj.set('proof', obj.id);
|
||||
obj.save().then(function(){
|
||||
promise.resolve();
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
return promise;
|
||||
}
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('AfterSaveTest2');
|
||||
obj.save().then(function(){
|
||||
done();
|
||||
})
|
||||
|
||||
let query = new Parse.Query('AfterSaveTest2');
|
||||
query.equalTo('proof', obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results.length).toEqual(0);
|
||||
},
|
||||
function(error) {
|
||||
fail(error);
|
||||
});
|
||||
});
|
||||
|
||||
it('test afterSave rejecting promise', function(done) {
|
||||
Parse.Cloud.afterSave('AfterSaveTest2', function(req) {
|
||||
let promise = new Parse.Promise();
|
||||
setTimeout(function(){
|
||||
promise.reject("THIS SHOULD BE IGNORED");
|
||||
}, 1000);
|
||||
|
||||
return promise;
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('AfterSaveTest2');
|
||||
obj.save().then(function(){
|
||||
done();
|
||||
}, function(error){
|
||||
fail(error);
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('test afterDelete returning promise, object is deleted when destroy resolves', function(done) {
|
||||
Parse.Cloud.afterDelete('AfterDeleteTest2', function(req) {
|
||||
let promise = new Parse.Promise();
|
||||
|
||||
setTimeout(function(){
|
||||
let obj = new Parse.Object('AfterDeleteTestProof');
|
||||
obj.set('proof', req.object.id);
|
||||
obj.save().then(function(){
|
||||
promise.resolve();
|
||||
});
|
||||
|
||||
}, 1000);
|
||||
|
||||
return promise;
|
||||
});
|
||||
|
||||
let errorHandler = function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
}
|
||||
|
||||
let obj = new Parse.Object('AfterDeleteTest2');
|
||||
obj.save().then(function(){
|
||||
obj.destroy().then(function(){
|
||||
let query = new Parse.Query('AfterDeleteTestProof');
|
||||
query.equalTo('proof', obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results.length).toEqual(1);
|
||||
let deletedObject = results[0];
|
||||
expect(deletedObject.get('proof')).toEqual(obj.id);
|
||||
done();
|
||||
}, errorHandler);
|
||||
}, errorHandler)
|
||||
}, errorHandler);
|
||||
});
|
||||
|
||||
it('test afterDelete ignoring promise, object is not yet deleted', function(done) {
|
||||
Parse.Cloud.afterDelete('AfterDeleteTest2', function(req) {
|
||||
let promise = new Parse.Promise();
|
||||
|
||||
setTimeout(function(){
|
||||
let obj = new Parse.Object('AfterDeleteTestProof');
|
||||
obj.set('proof', req.object.id);
|
||||
obj.save().then(function(){
|
||||
promise.resolve();
|
||||
});
|
||||
|
||||
}, 1000);
|
||||
|
||||
return promise;
|
||||
});
|
||||
|
||||
let errorHandler = function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
}
|
||||
|
||||
let obj = new Parse.Object('AfterDeleteTest2');
|
||||
obj.save().then(function(){
|
||||
obj.destroy().then(function(){
|
||||
done();
|
||||
})
|
||||
|
||||
let query = new Parse.Query('AfterDeleteTestProof');
|
||||
query.equalTo('proof', obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results.length).toEqual(0);
|
||||
}, errorHandler);
|
||||
}, errorHandler);
|
||||
});
|
||||
|
||||
it('test beforeSave happens on update', function(done) {
|
||||
Parse.Cloud.beforeSave('BeforeSaveChanged', function(req, res) {
|
||||
req.object.set('foo', 'baz');
|
||||
|
||||
@@ -895,7 +895,7 @@ RestWrite.prototype.runAfterTrigger = function() {
|
||||
this.config.liveQueryController.onAfterSave(updatedObject.className, updatedObject, originalObject);
|
||||
|
||||
// Run afterSave trigger
|
||||
triggers.maybeRunTrigger(triggers.Types.afterSave, this.auth, updatedObject, originalObject, this.config);
|
||||
return triggers.maybeRunTrigger(triggers.Types.afterSave, this.auth, updatedObject, originalObject, this.config);
|
||||
};
|
||||
|
||||
// A helper to figure out what location this operation happens at.
|
||||
|
||||
@@ -86,8 +86,7 @@ function del(config, auth, className, objectId, clientSDK) {
|
||||
objectId: objectId
|
||||
}, options);
|
||||
}).then(() => {
|
||||
triggers.maybeRunTrigger(triggers.Types.afterDelete, auth, inflatedObject, null, config);
|
||||
return;
|
||||
return triggers.maybeRunTrigger(triggers.Types.afterDelete, auth, inflatedObject, null, config);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -209,7 +209,20 @@ export function maybeRunTrigger(triggerType, auth, parseObject, originalParseObj
|
||||
Parse.masterKey = config.masterKey;
|
||||
// For the afterSuccess / afterDelete
|
||||
logTrigger(triggerType, parseObject.className, parseObject.toJSON());
|
||||
trigger(request, response);
|
||||
|
||||
//AfterSave and afterDelete triggers can return a promise, which if they do, needs to be resolved before this promise is resolved,
|
||||
//so trigger execution is synced with RestWrite.execute() call.
|
||||
//If triggers do not return a promise, they can run async code parallel to the RestWrite.execute() call.
|
||||
var triggerPromise = trigger(request, response);
|
||||
if(triggerType === Types.afterSave || triggerType === Types.afterDelete)
|
||||
{
|
||||
if(triggerPromise && typeof triggerPromise.then === "function") {
|
||||
return triggerPromise.then(resolve, resolve);
|
||||
}
|
||||
else {
|
||||
return resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user