JavaScript与Ajax调用中的诺言链

时间:2019-05-27 23:32:17

标签: javascript promise

我有一个函数(f1),只有在完成两个ajax调用(例如a1和a2)之后,我才想调用该函数。只有在a1完成后才应调用a2。以下是操作顺序=

$.when(a1 and a2) {
   f1
}

我尝试了以下代码片段-

$.when(a1a2()).done(function(){
  f1();
}

var a1a2 = function(){
  return $.when(a1()).done(function() {
    if (<check for a few variables a1 sets>) {
      // another ajax call for which f1 should wait
      return a2();
    } else {
      // random function for which f1 shouldn't wait
      f2();
    }
  });
}

在上面的代码中,f1等待a1完成,但不等待a2完成。

我也尝试了以下代码片段(但这也只是等待a1完成)-

var a1a2 = function(){
  var retVal = new Promise(function(){
    a1().then(function(){
      if (<check for a few variables a1 sets>) {
        return a2();
      } else {
        // random function for which f1 shouldn't wait
        f2();
      }
    });
  });
}

我看过其他类似的问题,但无法制定解决方案。有人可以帮忙吗?

4 个答案:

答案 0 :(得分:2)

调用a1以获得承诺,然后在Promise.alla1上与a1链接的a2上调用:

const a1Prom = a1();
Promise.all([
  a1Prom,
  a1Prom.then(a2)
])
  .then(f1);

console.log('script start');

const delay = ms => new Promise(res => setTimeout(res, ms));
const a1 = () => delay(1000).then(() => console.log('a1 done'));
const a2 = () => {
  console.log('a2 starting');
  return delay(1000).then(() => console.log('a2 done'));
};

const f1 = () => console.log('f1 starting');



const a1Prom = a1();
Promise.all([
  a1Prom,
  a1Prom.then(a2)
])
  .then(f1);

答案 1 :(得分:1)

首先,您的Promise代码有误,因为您没有正确创建Promise

new Promise(function(resolve, reject) {
    // in here you call resolve or reject otherwise Promise is forever pending
});

但是,由于a1返回了Promise(我假设所有功能都一​​样),因此您无需创建Promise

因此,您的代码应为

a1()
.then(function() {
    if (somecondition == true) {
        return a2();
    } else {
        f2(); // since there's no return here, there's no "wait" for the promise f2 returns
    }
})
.then(function() {
    return f1();
})

为说明上述内容,这是您的代码,条件为true,然后条件为false

记下控制台输出的“时间戳记”

// dummy code to set up some promises
const dummy = (x, d=1000) => {
    console.log(performance.now(), 'start', x);
    return new Promise(resolve => setTimeout(() => {
        console.log(performance.now(), 'end', x);
        resolve(x);
    }, d));
};

const a1 = () => dummy('a1');
const a2 = () => dummy('a2');
const f1 = () => dummy('f1');
const f2 = () => dummy('f2', 3000);

// end dummy code

console.log('wait for a2');
a1()
.then(function() {
    if (true) {
        return a2();
    } else {
        // random function for which f1 shouldn't wait
        f2();
    }
})
.then(function() {
    return f1();
})
.then(() => {
    console.log('dont wait for f2');
    a1()
    .then(function() {
        if (false) {
            return a2();
        } else {
            // random function for which f1 shouldn't wait
            f2();
        }
    })
    .then(function() {
        f1();
    });
});

  

但是!如果f2是一个没有异步功能的函数,则无法 * 阻止f2完成后调用f1-因为这就是javascript的工作方式

     

* -我猜您可以将其放在setTimeout中,然后f2将在f1开始之后执行(同样,假设f1具有一些异步性,否则f2将在之后开始f1结束)

答案 2 :(得分:0)

我不熟悉when / done语法,但这是对第二个代码段的更正。我要给出的一个重要提示是,使用new Promise在90%的情况下是一个坏主意。

var a1a2 = function(){
  var retVal = a1().then(function(){
    if (<check for a few variables a1 sets>) {
      return a2();
    } else {
      // random function for which f1 shouldn't wait
      f2();
    }
  });
});

答案 3 :(得分:0)

function a1() {
  return new Promise(resolve => { 
     resolve();
  });
}

function a2() {
  return new Promise(resolve => {
    resolve();
  });
}

function f1() {
  // this runs when the a1 and a2 is resolved.
}

// this is the call method. there are so many approach in your question first is chaining of promise.
function CallMethod(){
   a1().then(function () { // you can optionally pass data here via the resolve in the promise
      return a2();
   }).then(function () { // same here you can pass optional data here.
      // here the a1 and a2 is resolved you can call the f1() now.
      f1();
   });
}
// second one is called Promise.all()
function CallMethod() {
  Promise.all([a1(), a2()]).then(data => { // this is the optional data passed in the resolve base on the index of the function promises. 
     var firstResolve = data[0]; // resolved data of a1();
     var secondResolve = data[1]; // resolved data of a2();
  })
}