入门前端-《JavaScript 语言入门教程-callback、Promise、async和await》

callback 回调函数

定义:被作为实参传入另一函数,并在该外部函数内被调用,用以来完成某些任务的函数,称为回调函数。

为什么要使用回调函数?

回调函数分为同步回调函数和异步回调函数。我们常用的也是异步回调函数,比如网络请求后台数据,我们不知道数据什么时候返回,所以用异步回调函数处理返回结果。

同步回调函数:会立即执行的函数

function greeting(name) {
  alert('Hello ' + name);
}

function processUserInput(callback) {
  let name = prompt('请输入你的名字。');
  callback(name);
}

processUserInput(greeting);

异步函数:不会立即执行的函数

function greeting(name) {
  alert('Hello ' + name);
}

function processUserInput(callback) {
  let name = prompt('请输入你的名字。');
  // 延迟一秒后执行
  setTimeout(function(){ callback(name); }, 1000);
}

processUserInput(greeting);

怎么使用回调函数?

从上面的示例可以看到,回调函数的使用很简单,只需要在函数的参数里面填入callback 函数,然后在函数体里面合适的位置调用callback函数即可。

回调地狱

在使用JavaScript时,为了实现某些逻辑经常会写出层层嵌套的回调函数,如果嵌套过多,会极大影响代码可读性和逻辑,这种情况被成为回调地狱。

看看下面的代码:

// 回调方法
let stepFunc= function (name, callback) {
  setTimeout(function () {
    console.log(name);
    callback();
  }, 1000);
}
// 回调嵌套
stepFunc("第一步", function () {
  stepFunc("第二步", function () {
    stepFunc("第三步", function () {
      console.log("结束");
    });
  });
});
// 输出:
> "第一步"
> "第二步"
> "第三步"
> "结束"

Promise

解决什么问题

Promise 是一个对象,它代表了一个异步操作的最终完成或者失败。

不同于callback函数,在使用 Promise 时,会有以下约定:

  • 在本轮 函数 运行完成之前,promise的回调函数是不会被调用的。
  • 即使异步操作已经完成(成功或失败),在这之后通过 then() 添加的回调函数也会被调用。
  • 通过多次调用 then() 可以添加多个回调函数,它们会按照插入顺序进行执行。

如何使用

let stepFunc = function (name) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      console.log(name);
      resolve();  //在异步操作执行完后执行 resolve() 函数
    }, 1000);
  });
}
stepFunc("第一步")
.then(function () {
  return stepFunc("第二步");  //仍然返回一个 Promise 对象
}).then(function () {
  return stepFunc("第三步");
}).then(function () {
  console.log('结束');
}).catch(function (err) {
  console.log(err);
}).finally(function (err) {
  console.log('finally');
})
// 输出
> "第一步"
> "第二步"
> "第三步"
> "结束"
> "finally"

Promise多异步任务合并用法

Promise.all(iterable)

这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。Promise.all方法常被用于处理多个promise对象的状态集合。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]

Promise.race(iterable)

iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。

const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'one');
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then((value) => {
  console.log(value);
  // Both resolve, but promise2 is faster
});
// expected output: "two"

Promise.all 和 Promise.race 的区别

  • Promise.all 只要集合里面有一个Promise返回失败则整体返回失败,集合中的返回结果是有顺序的。
  • Promise.race 返回结果是集合中某个执行时间最短的Promise的结果。

Promise 和 callback 的区别

  • 纯粹的callBack回调因为剥夺了函数的回调能力,所以当函数的调用层数很多的时候,需要层层传递callBack
  • Promise不需要层层传递callBack,因为它使函数具备了return的能力。使得函数调用变成了链式写法。不仅改善了可读性,而且对于多层嵌套的回调函数尤其方便。
  • 对于多个异步需要合并的情况下,用纯粹的callback 是相当麻烦的,但是Promise很好的解决这个问题
  • Promise是一个对象,不同于函数,对象能保留状态,而函数在被调用需要马上返回状态。

async/await

async函数是使用async关键字声明的函数。 async函数是AsyncFunction构造函数的实例, 并且其中允许使用await关键字。asyncawait关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用Promise

解决什么问题

用同步的方式写出异步的代码。

如何使用

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  console.log('calling');
  const result = await resolveAfter2Seconds();
  console.log(result);
  // expected output: "resolved"
}

// 使用时需要做捕获异常
try{
	asyncCall();
}catch(e){
	console.error(e)
}


// 先输出 calling 然后隔两秒输出 resolved
> "calling"
> "resolved"

async/await 和 promise 的区别

  • Promise 是异步编程的一种解决方案
  • asyncawait 是语法糖,作用是让我们能够像写同步代码一样编写异步代码
  • async用来声明一个异步方法,返回的是一个promise对象
  • await 结果是promisethen取值
  • await只能在async方面的里面使用,让后面的执行语句或方法要等待当前await方法的结果后才能再执行。

总结

处理异步代码的过程中我们使用了callback回调函数,但是回调函数嵌套过多会影响代码的可读性也不方便维护,所以ES6中新增了Promise特性可以解决异步问题,但是代码样式看起来还是有异步的味道,故ES8新增了async/await 特性,让我们的代码可以像同步代码一样写异步代码。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_龙衣

赏杯快乐水喝喝

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值