JQuery Deferred - 在链定义后添加回调

时间:2013-10-10 14:27:38

标签: jquery callback promise deferred

var $jobApplication = $.Deferred();
$jobApplication
  .progress( displayState )
  .done( acceptContract )
  .done( relocate )
  .fail( keepCalmAndDrinkWine );

function displayState(payload){
  console.log(payload.state);

  if (payload.job){
    $jobApplication.resolve(payload.job); 
  }
}

$jobApplication.notify({
  state: "shortlist"
});

$jobApplication.notify({
  state: "phone_interview",
  date: "2013-01-23"
});

$jobApplication.notify({
  state: "technical_interview",
  date: "2013-02-11"
});

$jobApplication.notify({
  state: "physical_interview",
  date: "2013-02-14"
});

$jobApplication.notify({
  state: "salary_negociation",
  job: {
    role: "Software Engineer",
    company: "BBC",
    starts: "2013-03-04"
  },
  date: "2013-02-14"
});


function acceptContract(jobOffer){
  console.log("Contract accepted with the following details: ");
  console.log(jobOffer);
}

function keepCalmAndDrinkWine(err){
  console.log("Too bad it did not work for this reason: %s ", err); 
}

function relocate(){
  console.log("Relocating (a new Promise ;-)) ");
}

这是我描述一些我遇到麻烦的问题的例子。

我想为“acceptContract”函数添加一些回调。当“acceptContract”运行时,我的新回调会立即运行。

例如,我的第一个解决方案是添加此代码。

acceptContract = $jobApplication.promise();

acceptContract.done(function () {
    console.log('call your mom')
}).done(function () {
    console.log('be happy')
})

这个代码工作但一个小故障。链完成后工作。

控制台:

这就是我得到的:

phone_interview
technical_interview
physical_interview
salary_negociation
Contract accepted with the following details:
Object {role: "Software Engineer", company: "BBC", starts: "2013-03-04"} 
Relocating (a new Promise ;-))
call your mom 
be happy

这是我所期待的:

phone_interview
technical_interview
physical_interview
salary_negociation
Contract accepted with the following details:
Object {role: "Software Engineer", company: "BBC", starts: "2013-03-04"}
call your mom 
be happy
Relocating (a new Promise ;-))

1 个答案:

答案 0 :(得分:0)

你有点滥用承诺模式。两点:

  • 对promise的回调不应影响它的状态。您正在从进度监听器解析它,而是通知延迟的进程应触发进度事件并从自身解决承诺。
  • 回调的顺序定义为FAFC(首先附加 - 首先调用),但更值得注意的是回调必须(应该)不相互依赖。这打败了纯粹的设计,使代码不那么干净。相反,如果你想要在另一个之后发生一个动作,你应该用then链接它们,为“第一个承诺之后执行的动作”创建一个新的承诺,然后你可以为第二个动作附加监听器。通常这意味着新的承诺将通过第二个动作所需的第一个动作的结果来解决,在您的情况下,您只需要没有值的时间链接。

function applyForJob() {
    var application = $.Deferred();
    return {
        step: function(payload) {
            application.notify(payload.state);
            if (payload.job)
                application.resolve(payload.job);
        },
        promise: application.promise()
    };
}

var $jobApplication = applyForJob();
$jobApplication.promise
  .progress( console.log.bind(console) )
  .fail( keepCalmAndDrinkWine );

var acceptedContract = $jobApplication.promise
  .then(acceptContract)
  .then(function() {
      console.log('call your mom');
      console.log('be happy');
  });
acceptedContract.done( relocate );

$jobApplication.step({
  state: "shortlist"
});

$jobApplication.step({
  state: "phone_interview",
  date: "2013-01-23"
});

$jobApplication.step({
  state: "technical_interview",
  date: "2013-02-11"
});

$jobApplication.step({
  state: "physical_interview",
  date: "2013-02-14"
});

$jobApplication.step({
  state: "salary_negociation",
  job: {
    role: "Software Engineer",
    company: "BBC",
    starts: "2013-03-04"
  },
  date: "2013-02-14"
});


function acceptContract(jobOffer){
  console.log("Contract accepted with the following details: ");
  console.log(jobOffer);
}

function keepCalmAndDrinkWine(err){
  console.log("Too bad it did not work for this reason: %s ", err); 
}

function relocate(){
  console.log("Relocating (a new Promise ;-)) ");
}