如何使用Backbone.Model.save()承诺验证

时间:2013-09-20 00:48:21

标签: backbone.js jquery-deferred

我正在尝试使用Backbone.model.save()返回的承诺。实际上,根据规范,如果有效则返回一个promise,否则返回false。我想在将来的deferred.done()deferred.fail()来电中使用返回值,无论其类型如何。像这样:

var promise = model.save();

$.when(promise).done(function() {
   console.log('success!');
});

$.when(promise).fail(function() {
   console.log('dang');
});

但是,$.when()在传递非承诺时会done(),所以,在上面,如果模型无效,$.when(false).done()会触发,你会获得“成功!”

我知道我可以使用success中的errorsave()属性,但是对于我的代码,稍后应用多个done()函数是有利的。这就是承诺的力量。

所以,我离开了:

var promise = model.save();

if (promise) {
    $.when(promise).done(function() {
        console.log('success!');
    });

    $.when(promise).fail(function() {
        console.log('dang');
    });
} else {
    console.log('dang');
}

我讨厌不干。

var promise = model.save();

var fail = function() {
    console.log('dang');
};

if (promise) {
    $.when(promise).done(function() {
        console.log('success!');
    });

    $.when(promise).fail(function() {
        fail();
    });
} else {
    fail();
}

变得非常混乱。你得到了照片。我希望我在这里错过一些东西。

2 个答案:

答案 0 :(得分:6)

您可以覆盖Backbone.save方法以获得所需的行为。如果原始保存函数的返回值是布尔值(这意味着验证失败),则只返回自定义承诺并拒绝其相关的延迟。

var oldSaveFunction = Backbone.Model.prototype.save;
Backbone.Model.prototype.save = function(){
    var returnedValue = oldSaveFunction.apply(this, arguments),
        deferred = new $.Deferred();

    if(_.isBoolean(returnedValue)){
        deferred.reject();
        return deferred.promise();
    }

    return returnedValue;
}

var Person = Backbone.Model.extend({
    url : 'http://www.google.com',
    validate : function(attributes){
         if(!("name" in attributes))
             return "invalid";
    }
});

var person = new Person();
$.when(person.save()).fail(function(){
   console.log("failed"); 
});

试试这个小提琴

http://jsfiddle.net/WNHXz/1/

答案 1 :(得分:1)

这是对先前答案的改进,但更好地支持错误处理。我需要它来避免吞咽错误,所以这就是我所做的:

var oldSaveFunction = Backbone.Model.prototype.save;
Backbone.Model.prototype.save = function () {
  var returnedValue = oldSaveFunction.apply(this, arguments),
    fulfiller,
    rejecter,
    pendingPromise = new Promise(function (fulfill, reject) {
      fulfiller = fulfill;
      rejecter = reject;
    });

  if (_.isBoolean(returnedValue)) {
    rejecter(this.validationError);
  } else {
    // Assuming returnedValue is a deferred
    returnedValue.then(function success() {
      fulfiller.apply(this, arguments);
    }, function failure(jqxhr, errorName, error) {
      rejecter(error);
    });
  }

  return pendingPromise;
};

希望它有所帮助!