0
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 ;-))
4

1 回答 1

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 ;-)) ");
}
于 2013-10-11T13:55:57.513 回答