How can you use a callback to guarantee sequential execution?

喜夏-厌秋 提交于 2020-01-16 08:37:07

问题


I am trying to wrap my head around callbacks and I do not understand how callbacks guarantee that a statement will execute after(in terms of time) another statement which takes an unknown amount of time. I do not care about promises,await,async, etc but just plain callbacks as I am trying to learn.


For example below, my method will execute the callback before the unknown time event has occured. I can see how callbacks can be used to execute something because an event occurred but not how they can be used to guarantee that something will be executed after(in terms of time) something else has finished executing and returned something meaningful.

function foo(callback) {
    setTimeout(() => console.log("Do something with unknown time"),
        2000);
    callback();
}

function callback() {
    console.log("Execute callback");
}

foo(callback);

So what I am asking is can callbacks be used to guarantee execution sequence in the time domain ? Or is their only purpose responding to events ?


回答1:


Callbacks is a way of invoking a function that is passed as a parameter to invoker function(in your example foo). Callbacks guarantee that a function will be invoked if no error occurs before it's call inside the function. Callbacks aren't asynchronous either but the way it executes later inside the function after some line of code makes everyone think it as asynchonous at first.

And as you've added setTimeout function on the above example, setTimeout is an asynchronous callback envoker function that calls it's callback(in your code () => console.log("Do something with unknown time")) asynchronously after a certain defined time(2000). So, setTimeout wont stop the execution for 2 seconds as you've expected, instead it let's the further line of codes execute without worrying about what will happen inside it's callback. So, the callback() will trigger at that instant when foo(callback); is triggered.

You can find more info about callback in here.




回答2:


You have asked two questions,

  1. Is callback execution sequence guaranteed?

  2. Is callback only respond to events ?

Answer

  1. Yes.

From my understanding, callback is just calling another function to be run now (when it is called)

It is guarantee to run immediately when you call it.

To ensure something is called before the callback is triggered, simply put the things you want to call execute first before callback is conducted.

e.g. from your code, by modify it a bit, callback is guarantee to run after the console.log is executed.

function foo(callback) {
    setTimeout(() => {
        console.log("Do something with unknown time");
        callback();
    }, 2000);
}

function callback() {
    console.log("Execute callback");
}

foo(callback);

It is the setTimeout which defers the execution, and is not related to callback methodology.

  1. Sure, callback can be used as a callback to respond to event, just like elem.addEventListener("click", callback);. But not only that.

A simple example will be illustrated below.

e.g.

var map = function(arr, callback) {
  var result = [];
  for (var i = 0, len = arr.length; i < len; i++) {
    result.push(callback(arr[i]));
  }
  return result;
};

map([0, 1, 2, 3], function(item) {
  return item * 2;
})

Edited

This edit is referring to

For example, if I am making a database call, I do not know how much time it is going to take for the data to be retrieved. If i try to access it before it has arrived, I'll get an error.

Calling a database, is by no means different from an async http request. So here, I will use XMLHttpRequest to demonstrate how to use callback to ensure this. But normally, these are features provided in browser or node.js already. So you do not need to write it by your own. Of course, to prevent callback hell, I will personally prefer use of Promise or async/await. But this is a bit out of topic.

So let see how XMLHttpRequest can use callback to handle async task.

var sendRequest = function(callback) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
       callback(this); 
    }
  };
  xhttp.open("GET", "filename", true);
  xhttp.send();
}

and you can use callback to handle async event. Sometime you dont know when it will happen. And the basic idea how it works is from the example I have said in answer 1.




回答3:


If I understand you mean correctly, you can use callback as an event to do something, such as: onerror, oncomplete...

In this example, we start to run todo function, and we have oncomplete function which can be used as callback to do something after completing works on todo function.

While running, if there is some error, it will be logged to onerror function.

function todo(oncomplete, onerror) {
    try {
        console.log("Start...");

        console.log("Do something with unknown time");

        setTimeout(() => oncomplete(),2000);
        
        // you can try to throw error here to test
        // throw new Error("Some error message...");
    } catch (e) {
        onerror(e);
    }
}

function oncomplete() {
    console.log("Done!");
}

function onerror(e) {
    console.error(e.message);
}

todo(oncomplete, onerror);


来源:https://stackoverflow.com/questions/59728065/how-can-you-use-a-callback-to-guarantee-sequential-execution

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!