|
601 | 601 | // `set(attr).save(null, opts)` with validation. Otherwise, check if
|
602 | 602 | // the model will be valid when the attributes, if any, are set.
|
603 | 603 | if (attrs && !wait) {
|
604 |
| - if (!this.set(attrs, options)) return false; |
| 604 | + if (!this.set(attrs, options)) return Backbone.Promise.reject(this.validationError); |
605 | 605 | } else {
|
606 |
| - if (!this._validate(attrs, options)) return false; |
| 606 | + if (!this._validate(attrs, options)) return Backbone.Promise.reject(this.validationError); |
607 | 607 | }
|
608 | 608 |
|
609 | 609 | // After a successful server-side save, the client is (optionally)
|
|
639 | 639 | // Optimistically removes the model from its collection, if it has one.
|
640 | 640 | // If `wait: true` is passed, waits for the server to respond before removal.
|
641 | 641 | destroy: function(options) {
|
642 |
| - options = options ? _.clone(options) : {}; |
| 642 | + options = _.extend({}, options); |
643 | 643 | var model = this;
|
644 | 644 | var success = options.success;
|
645 | 645 | var wait = options.wait;
|
|
655 | 655 | if (!model.isNew()) model.trigger('sync', model, resp, options);
|
656 | 656 | };
|
657 | 657 |
|
658 |
| - var xhr = false; |
| 658 | + var xhr; |
659 | 659 | if (this.isNew()) {
|
660 |
| - _.defer(options.success); |
| 660 | + xhr = Backbone.Promise.resolve().then(options.success); |
661 | 661 | } else {
|
662 | 662 | wrapError(this, options);
|
663 | 663 | xhr = this.sync('delete', this, options);
|
|
1408 | 1408 | return Backbone.$.ajax.apply(Backbone.$, arguments);
|
1409 | 1409 | };
|
1410 | 1410 |
|
| 1411 | + // A psuedo Promise implementation used to ensure asynchronous methods |
| 1412 | + // return thenables. |
| 1413 | + // Override this if you'd like to use a different ES6 library. |
| 1414 | + Backbone.Promise = function() { |
| 1415 | + throw new Error('Backbone does not provide a spec compliant Promise by default.'); |
| 1416 | + }; |
| 1417 | + |
| 1418 | + // A helper method that forces jQuery's first `then` callback to be |
| 1419 | + // executed asynchronously. |
| 1420 | + // This is used so we can guarantee our async return values execute |
| 1421 | + // callbacks async, not async sometimes and sync other times. |
| 1422 | + var asyncDeferred = function(method) { |
| 1423 | + return function(value) { |
| 1424 | + var deferred = Backbone.$.Deferred(); |
| 1425 | + _.defer(deferred[method], value); |
| 1426 | + return deferred.promise(); |
| 1427 | + }; |
| 1428 | + }; |
| 1429 | + |
| 1430 | + _.extend(Backbone.Promise, { |
| 1431 | + resolve: asyncDeferred('resolve'), |
| 1432 | + reject: asyncDeferred('reject') |
| 1433 | + }); |
| 1434 | + |
1411 | 1435 | // Backbone.Router
|
1412 | 1436 | // ---------------
|
1413 | 1437 |
|
|
0 commit comments