JavaScript异步学习 原创

zhushangyuan_
发布于 2023-7-31 08:46
浏览
0收藏

JavaScript异步学习

学习下JavaScript异步,边学边记录。分享如果同样需要学习的你。

1、JavaScript Callbacks

call back有回电话,招回来,喊回来的意思。在编程语言中,指的是回调函数。回调函数是一种作为参数传递给其他函数的函数,这种技术就允许一个函数调用另外一个函数。回调函数能在另外一个函数完成后执行。

1.1 Function Sequence 函数执行顺序

JavaScript函数按调用的顺序执行,而不是定义的顺序,下面的例子会先执行myFirst(),然后执行mySecond(),最后名称为"demo"的页面元素,会展示为"Goodbye"。如果想体验运行下,可以访问https://www.w3schools.com/Js/tryit.asp?filename=tryjs_callback1

function myDisplayer(some) {
  document.getElementById("demo").innerHTML = some;
}

function myFirst() {
  myDisplayer("Hello");
}

function mySecond() {
  myDisplayer("Goodbye");
}

myFirst();
mySecond();

1.2 Sequence Control 顺序控制

有的场景下,需要控制什么时候执行一个函数。假设需要进行一个计算,然后展示结果。你需要先调用myCalculator函数,保存结果,然后调用另外一个函数myDisplayer展示结果,如下:

function myDisplayer(some) {
  document.getElementById("demo").innerHTML = some;
}

function myCalculator(num1, num2) {
  let sum = num1 + num2;
  return sum;
}

let result = myCalculator(5, 5);
myDisplayer(result);

或者,你也可以这样写:

function myDisplayer(some) {
  document.getElementById("demo").innerHTML = some;
}

function myCalculator(num1, num2) {
  let sum = num1 + num2;
  myDisplayer(sum);
}

myCalculator(5, 5);

上面第一个例子的问题是,不得不写两个函数来展示结果。第二个例子的问题是,在计算函数里也一直会展示结果。下面就看,如何使用回调函数来解决这些问题。

2、JavaScript Callbacks

A callback is a function passed as an argument to another function. 回调是一种作为参数传递给另外一个函数的函数。

可以使用回调函数myCallback作为参数,调用计算函数myCalculator。计算函数在完成计算后,执行回调函数来展示结果。

function myDisplayer(some) {
  document.getElementById("demo").innerHTML = some;
}

function myCalculator(num1, num2, myCallback) {
  let sum = num1 + num2;
  myCallback(sum);
}

myCalculator(5, 5, myDisplayer);

在这个例子中,myDisplayer是个回调函数,作为参数传递给计算函数myCalculator

注意:当把函数作为参数传递时,不需要括号,如下:

Right: myCalculator(5, 5, myDisplayer);

Wrong: myCalculator(5, 5, myDisplayer());

再看一个例子,在①处定义了一个数组。在④处定义一个函数,它有2个参数,第一个是个数组,第二个是个回调函数。会遍历数组,把每一个数组元素作为参数传递给回调函数,如果回调函数返回true,则把数组元素存入新数组,最后返回新数组。②处调用④处定义的函数,把给定的数组,使用回调函数过滤了一遍,该回调函数会过滤正数。③处把过滤后的数组传递给网页元素。

// Create an Array
① const myNumbers = [4, 1, -20, -7, 5, 9, -6];

// Call removeNeg with a callback
② const posNumbers = removeNeg(myNumbers, (x) => x >= 0);

// Display Result
③ document.getElementById("demo").innerHTML = posNumbers;

// Keep only positive numbers
④ function removeNeg(numbers, callback) {
  const myArray = [];
  for (const x of numbers) {
    if (callback(x)) {
      myArray.push(x);
    }
  }
  return myArray;
}

在该例子中,(x) => x >= 0是个回调函数,作为参数传递给removeNeg()。回调函数也可以接受参数。

3、When to Use a Callback? 什么时候使用回调

这些例子没有什么意思,主要演示下回调函数的语义。回调函数真正有价值的地方是用在异步函数里,一个函数不得不等待另外一个函数,如等待文件上传。关注后文了解异步函数。

4、Waiting for a Timeout

上文解释了回调函数的语义,在编程实践中,回调经常和异步函数一起使用,在JavaScript中典型的例子为setTimeout()

当使用 JavaScript函数 setTimeout()时,可以指定一个时间到期后执行的回调函数。

setTimeout(myFunction, 3000);

function myFunction() {
  document.getElementById("demo").innerHTML = "I love You !!";
}

在这个例子中,myFunction作为回调函数使用,作为参数传递给函数 setTimeout()。3000ms即3秒后,回调函数才会被调用。

除了传递函数名称,也可以传递完整的函数,如下:

setTimeout(function() { myFunction("I love You !!!"); }, 3000);

function myFunction(value) {
  document.getElementById("demo").innerHTML = value;
}

5、Waiting for Intervals

当使用JavaScript函数 setInterval()时, 可以指定回调函数在指定的每个时间间隔执行。如下:

setInterval(myFunction, 1000);

function myFunction() {
  let d = new Date();
  document.getElementById("demo").innerHTML=
  d.getHours() + ":" +
  d.getMinutes() + ":" +
  d.getSeconds();
}

在该例子中,myFunction是个回调函数,作为参数传递给setInterval()。实现了每一秒钟,执行一次回调函数,完成了一个时钟的效果。

6、Callback Alternatives 什么时候使用回调

在异步编程时,JavaScript程序可以启动长时间的任务,然后平行的去运行其他任务。

但是,异步程序难以编写和调试。在现代异步JavaScript方法不使用回调,替代的是,使用Promise。后续会继续介绍。

7、JavaScript Promise Object

JavaScript对象用于承诺一个结果,包含生产代码"Producing code"和消费代码"Consuming code",Promise就是链接两者的对象。

生产代码"Producing code"包含在创建Promise对象的函数内,就是需要一定执行时间的任务,消费代码"Consuming code"用于调用Promise对象,等待Promise有结果后才会执行then函数。

JavaScript Promise语义如下,其中myResolve, myReject为函数参数名称,也可以有其他的参数命名,第一个参数当生产代码"Producing code"需要成功的结果时调用,第二个参数返回失败的结果时调用。在then函数里,value和error属于Promise返回的成功或失败的结果。

let myPromise = new Promise(function(myResolve, myReject) {
// "Producing Code" (May take some time)

  myResolve(); // when successful
  myReject();  // when error
});

// "Consuming Code" (Must wait for a fulfilled Promise)
myPromise.then(
  function(value) { /* code if successful */ },
  function(error) { /* code if some error */ }
);

当生产代码"Producing code"获得结果时,会调用下面的回调函数中的一个,成功或失败分别调用不同的回调函数:

Result Call
Success myResolve(result value)
Error myReject(error object)

8、Promise Object Properties

Promise对象支持2个属性: stateresult

一个JavaScript Promise对象的状态为下面中的一个:

  • Pending

  • Fulfilled

  • Rejected

    当JavaScript Promise对象处于 “pending” (working)时,result结果为undefined。
    当JavaScript Promise对象处于 "fulfilled"时,result结果为一个值value。
    当JavaScript Promise对象处于 “rejected” 时,result结果是一个error对象。

myPromise.state myPromise.result
“pending” undefined
“fulfilled” a result value
“rejected” an error object

不能访问Promise的state和result属性。必须使用Promise的方法来处理promise。

9、Promise How To

使用Promise对象的示例如下:

myPromise.then(
  function(value) { /* code if successful */ },
  function(error) { /* code if some error */ }
);

Promise.then()需要两个参数,一个回调参数用于成功,一个回调用于失败。两个都是可选的,也可以只提供其中的一个。

function myDisplayer(some) {
  document.getElementById("demo").innerHTML = some;
}

let myPromise = new Promise(function(myResolve, myReject) {
  let x = 0;

// The producing code (this may take some time)

  if (x == 0) {
    myResolve("OK");
  } else {
    myReject("Error");
  }
});

myPromise.then(
  function(value) {myDisplayer(value);},
  function(error) {myDisplayer(error);}
);

在介绍Promise之后,我们继续看Async和Await。

10、Async Syntax

关键字async用在一个函数前,会让函数返回一个Promise。

async function myFunction() {
  return "Hello";
}

等价于:

function myFunction() {
  return Promise.resolve("Hello");
}

使用Promise的完整例子:

async function myFunction() {
  return "Hello";
}
myFunction().then(
  function(value) {myDisplayer(value);},
  function(error) {myDisplayer(error);}
);

也可以简化,只期望一个正常值,不返回error时,示例为:

async function myFunction() {
  return "Hello";
}
myFunction().then(
  function(value) {myDisplayer(value);}
);

11、Await Syntax

await关键字只能用在async函数内,该关键字让函数暂停执行,等待resolved的promise对象,然后再继续执行。

let value = await promise;

示例如下:

async function myDisplay() {
  let myPromise = new Promise(function(resolve, reject) {
    resolve("I love You !!");
  });
  document.getElementById("demo").innerHTML = await myPromise;
}

myDisplay();

12、参考资料

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2023-7-31 08:48:29修改
1
收藏
回复
举报
回复
    相关推荐