Пользовательские события изменения статуса в Javascript - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть асинхронная функция, которая выполняет различные задачи ожидания. Я пытаюсь сообщить своему пользовательскому интерфейсу в React, когда состояние функции изменяется или когда одна из задач завершена.

const foo = async () => {
    // trigger on load event

    await task1();
    // trigger task1 done event

    await task2();
    // trigger task2 done event

    await task3();
    // trigger on done event
}

Я также хочу иметь возможность указывать обратные вызовы для каждого события, например, так:

const bar = foo();
foo.on_load(() => {
    // some code goes here
});
foo.on_done(() => {
    // some code goes here
});

Другой альтернативой может быть что-то вроде этого:

const bar = foo();
foo.on('status_change', status => {
    // read the status here and do something depending on the status
})

Я читал о пользовательских событиях в JS, но не уверен, как их использовать для этого. Или, может быть, есть другой способ сделать это в React.

Любые идеи будут полезны. Спасибо!

РЕДАКТИРОВАТЬ

var uploadTask = storageRef.child('images/rivers.jpg').put(file);

// Register three observers:
// 1. 'state_changed' observer, called any time the state changes
// 2. Error observer, called on failure
// 3. Completion observer, called on successful completion
uploadTask.on('state_changed', function(snapshot){
  // Observe state change events such as progress, pause, and resume
  // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
  var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
  console.log('Upload is ' + progress + '% done');
  switch (snapshot.state) {
    case firebase.storage.TaskState.PAUSED: // or 'paused'
      console.log('Upload is paused');
      break;
    case firebase.storage.TaskState.RUNNING: // or 'running'
      console.log('Upload is running');
      break;
  }
}, function(error) {
  // Handle unsuccessful uploads
}, function() {
  // Handle successful uploads on complete
  // For instance, get the download URL: https://firebasestorage.googleapis.com/...
  uploadTask.snapshot.ref.getDownloadURL().then(function(downloadURL) {
    console.log('File available at', downloadURL);
  });
});

Я пытался добиться чего-то вроде приведенного выше кода, взятого из документации Firebase по загрузке файлов

Вот где я дошел до этого:

class Task {
  constructor() {
    this.first = null;
    this.second = null;
  }

  on(keyword, callback) {
    switch (keyword) {
      case "first":
        this.first = callback;
        break;
      case "second":
        this.second = callback;
        break;
      default:
        // throw new error
        break;
    }
  }
}

const timeout = async time => {
  return new Promise(resolve => setTimeout(resolve, time));
};

const foo = () => {
  const task = new Task();

  timeout(2000).then(async () => {
    task.first && task.first();
    await timeout(2000);
    task.second && task.second();
  });

  console.log("returning");
  return task;
};

const taskObject = foo();
taskObject.on("first", () => console.log("executing first callback"));
taskObject.on("second", () => console.log("executing second callback"));

Есть ли лучший способ сделать это - без вложенных потомков? Какой подход будет лучше и когда? EDIT - удалены вложенные пункты then и заменены на then и await

PS: для моих требований было бы достаточно иметь обратные вызовы. Это просто, чтобы я мог лучше понять концепцию. Спасибо!

Ответы [ 2 ]

0 голосов
/ 19 февраля 2020

Наилучшим вариантом будет использование обещаний, что означает, что каждый раз, когда обещание разрешается, вы будете получать уведомления, а затем будет выполняться каскадное обещание.

пример ниже из цепочки обещаний

var function3 = function(resolve, reject)
{
   try
   {
     //do some thing
     console.log('function3 called');
     resolve('function3 success');
   }
   catch(err)
   {
      reject(err);
   }
}

var function2 = function(resolve, reject)
{
   try
   {
     //do some thing
     console.log('function2 called');
     resolve('function2 success');
     //return new Promise(function3);
   }
   catch(err)
   {
      reject(err);
   }
}

var function1 = function(resolve, reject)
{
   try
   {
     //do some thing
     console.log('function1 called');
     resolve('function1 success');
   }
   catch(err)
   {
      reject(err);
   }
}






var promise = new Promise(function1);

promise
.then(function(response){
  console.log(response);
   return new Promise(function2);
}, function(error)
{
   console.log(error);
})
.then(function(response)
{
  console.log(response);
  return new Promise(function3);
},
function(err)
{
  console.log(error);
})
.then(function(response)
{
  console.log(response);
},
function(err)
{
  console.log(error);
})

//output
"function1 called"
"function1 success"
"function2 called"
"function2 success"
"function3 called"
"function3 success"

0 голосов
/ 19 февраля 2020

Я собираюсь предположить, что есть причина, по которой вы не просто вызываете какой-то именованный метод после завершения каждого шага asyn c, т. Е. Вы хотите иметь возможность подключать разные обработчики для каждого события. Вот один из способов go об этом - о том, является ли он лучшим, трудно определить из небольшого предоставленного контекста:

const foo = async (handlers) => {
  handlers.onLoad && handlers.onLoad();

  await task1();
  handlers.onTask1Complete && handlers.onTask1Complete();

  await task2();
  handlers.onTask2Complete && handlers.onTask2Complete();
}
const myHandlers = {
  onLoad: () => {
    // do stuff
  },
  onTask1Complete: () => {
    // do other stuff
  },
  onTask2Complete: () => {
    // etc
  }
};

foo(myHandlers);

Обратите внимание, что он позволяет указывать только нужные вам обработчики. Более гибкий подход был бы к модели publi sh -subscribe, где метод подписки помещает функцию в массив обработчиков, каждый из которых вызывается, когда происходит событие.

...