Цепочка обещаний в javascript с вызовами ajax

У меня есть функция (f1), которую я хочу вызывать только после выполнения двух вызовов ajax (скажем, a1 и a2). a2 следует вызывать только после того, как выполнено a1. Ниже приведена последовательность операций =

$.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();
      }
    });
  });
}

Я просмотрел другие подобные вопросы, но не смог найти решение. Может кто-нибудь помочь?

new Promise(function(){ это НЕ то, как вы создаете обещание - это обещание останется в ожидании навсегда
Jaromanda X 28.05.2019 02:04

Возможный дубликат Разрешить обещания одно за другим (т.е. последовательно)?

Heretic Monkey 28.05.2019 02:56
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
4
2
66
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Позвоните a1, чтобы получить свое Обещание, затем позвоните Promise.all на a1 и a1, связанном с a2:

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

console.info('script start');

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

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



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

Это не сработало для меня, оно не ждет выполнения a2. a2 не возвращает никаких обещаний

user2851669 28.05.2019 11:58

Да, вам нужно убедиться, что a2 возвращает промис, чтобы использовать его с асинхронным кодом, подобным этому (но вы не опубликовали код a2). Если вы это сделаете, нажмите «Выполнить фрагмент кода», вы увидите, что он работает как нужно.

CertainPerformance 28.05.2019 12:02

Есть ли способ вернуть обещание или ноль (если я не хочу ждать)

user2851669 28.05.2019 20:46

Я не знаком с синтаксисом 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();
    }
  });
});
Ответ принят как подходящий

Во-первых, ваш промис-код неверен, потому что вы неправильно создаете промис.

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

Однако, поскольку a1 возвращает обещание (как и все функции, я предполагаю), вам не нужно создавать обещание.

Итак, ваш код будет

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.info(performance.now(), 'start', x);
    return new Promise(resolve => setTimeout(() => {
        console.info(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.info('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.info('dont wait for f2');
    a1()
    .then(function() {
        if (false) {
            return a2();
        } else {
            // random function for which f1 shouldn't wait
            f2();
        }
    })
    .then(function() {
        f1();
    });
});

However! If f2 is a function that has no asynchrony then there is no way * to prevent f1 from being called after f2 finish - because that's how javascript works

* - I guess you could put it in a setTimeout, then f2 would execute after f1 begins (again, assuming f1 has some asynchrony, otherwise f2 would begin after f1 ends)

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();
  })
}

Другие вопросы по теме