JS Как привязать функцию на выполнение после обработки другой функции?

Есть необходимость выполнить функцию, после выполнения первой функции, но когда первая будет завершена(и будет ли), отследить сложно. Приведу простой пример что б объяснить сумбур вопроса.

/// WE CAN'T change this elements
const btn = document.getElementById("btn_push");
let sendData = (timeFunc) => { console.log(`Function DONE! It took ${timeFunc} sec`)};
let randomInteger = (min, max) => {
  let rand = min - 0.5 + Math.random() * (max - min + 1);
  return Math.round(rand);
}
btn.addEventListener("click", function(){
  const time = randomInteger(1000, 4000);
  setTimeout(sendData(time), time); 
});

/// OWN elements


let secondFunction = () => { console.log(`This function done after server get data`)};

Предположим имеется функция отправляющая данные на сервер sendData() по нажатию на кнопку. Сколько она будет выполняться (проводить валидации, общаться с другими API и тд.) нам не известно. Нам известно только её название, и то, что выполнение повешено на клик. Вопрос, как выполнить secondFunction() по завершению выполнения первой функции? *Вторая функция может вызываться совершенно с другого js файла этого же html документа. Возможно ли это как-то отловить, что она завершила действие?

PS Если б это всё было в одном js и можно б было переписать вызов первой функции, то делалось бы через Promise, но этого нету.


Ответы (3 шт):

Автор решения: Irshat Khuzin

Вы можете использовать метод setTimeout для запуска функции secondFunction после выполнения функции sendData. Вы можете передать функцию sendData в качестве аргумента в setTimeout, а затем в теле функции sendData вызвать secondFunction.

btn.addEventListener("click", function(){
  const time = randomInteger(1000, 4000);
  setTimeout(() => {
    sendData(time);
    secondFunction();
  }, time); 
});

Так же Вы можете использовать события, которые генерирует sendData(Event), и подписать secondFunction на это событие. Таким образом, secondFunction будет выполнятся только после того, как sendData генерирует событие.

document.addEventListener('sendDataEvent', secondFunction);
let sendData = (timeFunc) => { 
  console.log(`Function DONE! It took ${timeFunc} sec`);
  document.dispatchEvent(new Event('sendDataEvent'));
};
→ Ссылка
Автор решения: Sire IMPACTUS

Почему бы не переписать функцию?

const oldFunc = btn.onclick;

btn.onclick = function(e) {
    const data = oldFunc(e);
    sencodFunction();
    return data;
    //или
    setTimeout(sencodFunction, 200)
    return oldFunc(e);
}
→ Ссылка
Автор решения: ksa

let sendData = (timeFunc) => {...}; как выполнить secondFunction() по завершению выполнения первой функции?

Если sendData задана именно т.о. - можно использовать прокси объект и "подменить ее".

Если функция асинхронная - код будет выглядеть немного иначе. Но суть будет та же.

Если функция объявлена как const sendData = (timeFunc) => {...} - использование прокси не прокатит.

/// WE CAN'T change this elements
const btn = document.getElementById("btn_push");
let sendData = (timeFunc) => { console.log(`Function DONE! It took ${timeFunc} sec`)};
let randomInteger = (min, max) => {
  let rand = min - 0.5 + Math.random() * (max - min + 1);
  return Math.round(rand);
}
btn.addEventListener("click", function(){
  const time = randomInteger(1000, 4000);
  setTimeout(sendData(time), time); 
});

/// OWN elements


let secondFunction = () => { console.log(`This function done after server get data`)};
sendData = new Proxy(sendData, {
  apply: function(target, self, arg) {
    target.apply(self, arg)
    secondFunction()
}})
<button id='btn_push'>Тест</button>

Вот вариант с асинхронной функцией sendData...

/// WE CAN'T change this elements
const btn = document.getElementById("btn_push");
let sendData = (timeFunc) => new Promise(res => setTimeout(_ => {
console.log(`Function DONE! It took ${timeFunc} sec`)
res('какие-то данные')
}, timeFunc));
let randomInteger = (min, max) => {
let rand = min - 0.5 + Math.random() * (max - min + 1);
return Math.round(rand);
}
btn.addEventListener("click", function(){
const time = randomInteger(1000, 4000);
sendData(time)
    .then(v => console.log('Обработка', v))
});

/// OWN elements


let secondFunction = () => { console.log(`This function done after server get data`)};
sendData = new Proxy(sendData, {
apply: async function(target, self, arg) {
    const v = await target.apply(self, arg)
    secondFunction()
    return v
}})
<button id='btn_push'>Тест</button>

→ Ссылка