简体   繁体   中英

Why are my Javascript callbacks undefined?

In an HTML document, a script is run when the page loaded and the JS defines a series of chained together functions, all called whenever the previous one is done . I have a number of questions with this example:

  1. Why is f1 undefined?
  2. Am I supposed to be able to define functions f1 , ..., f4 also within callbacksInit , so as not to pollute the global namespace?
  3. Am I supposed to be able to define functions f1 , ..., f4 in the JS document after callbacksInit ?

 var f1 = function() { console.log("Running f1"); } var f2 = function() { console.log("Running f2"); } var f3 = function() { console.log("Running f3"); } var f4 = function() { console.log("Running f4"); } function callbacksInit() { function start() { f1().done(f2).done(f3).done(f4); } start(); }
 <.DOCTYPE html> <html> <head> <script type="text/javascript" src="./callbacks.js"></script> </head> <body onload="callbacksInit()"> <main> <h1>CALLBACKS ASYNC</h1> </main> </body> </html>

a function by itself does not return anything, hence the undefined

const a = () => { 
  console.log("Running f1"); 
}

// returns "undefined"
const b = () => { 
  console.log("Running f1"); 
  return 'b';
}

// returns "b"

BTW there is no such thing as done() apart of jQuery deferred mode , but to use that, you need to use jQuery, that's not in the tag

you need to return a Promise object, like

function a() {
  return new Promise( function(resolve, reject) {
    // now you can either:
    // return resolve('data')
    // return reject(new Error('My error message'))
  });
}

by returning a promise you can now use the normal callback hell ♂️

function callbacksInit() {
    function start() {
        f1()
        .then(function(data1) { f2() })
        .then(function(data2) { f3() })
        .then(function(data3) { f4() })
        .then(function(data4) { /* done, continue here */ })
        .catch(function(err) {
           console.log(err.message) // the message of the error upon reject()
        });
    }
    start();
}

or use async/await

function callbacksInit() {
    function async start() {
        try { // there's no "catch" in async/await so we wrap all in try/catch
           var data1 = await f1()
           var data2 = await f2()
           var data3 = await f3()
           var data4 = await f4()
       } catch(err) {
           console.log(err.message) // the message of the error upon reject()
       }
    }
    start();
}

Important NOTE

Always return an Error object when rejecting a Promise, will make things so much easier for you in the future

You are calling f1() which basically returns void, it doesn't return anything and then you are trying to access a function done() it it, but since the return value is undefined then it had nothing.

we are not talking about async functions here or anything, what's wrong with just calling them one after another?

f1()
f2()
f3()
f4()

This should do the trick, they are not async so each one will just run after the previous one has finished.

Am I missing something here?

The function f1 is defined, however the.done called on it is not. In order for you to actually execute the functions one after the other(considering each function has some async actions within it), you need to return Promise from them which resolves once the function is executed.

Also use.then instead of.done

 var f1 = function() { console.log("Running f1"); return Promise.resolve()} var f2 = function() { console.log("Running f2"); return Promise.resolve()} var f3 = function() { console.log("Running f3"); return Promise.resolve()} var f4 = function() { console.log("Running f4"); return Promise.resolve()} function callbacksInit() { function start() { f1().then(f2).then(f3).then(f4); } start(); }
 <.DOCTYPE html> <html> <head> <script type="text/javascript" src="./callbacks.js"></script> </head> <body onload="callbacksInit()"> <main> <h1>CALLBACKS ASYNC</h1> </main> </body> </html>

For a normal synchronous function, you can directly call them like

function callbacksInit() {
    function start() {
        f1();
        f2();
        f3();
        f4();
    }
    start();
}

and they will all execute one after the other

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM