JavaScript之 async/await与Promise

发布于:2024-06-13 ⋅ 阅读:(156) ⋅ 点赞:(0)

背景

Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务

ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等,而 ES2015 则是正式名称,特指该年发布的正式版本的语言标准。一般提到 ES6 的地方,一般是指 ES2015 标准,但有时也是泛指“下一代 JavaScript 语言”。

ECMAScript 当前的所有提案,可以在 TC39 的官方网站https://github.com/tc39/ecma262查看。

什么是Promise

MDN 官网:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
w3schools官网:https://www.w3schools.com/Js/js_promise.asp
阮一峰的ECMAScript 6 入门: https://es6.ruanyifeng.com/#docs/promise

Promise 是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。promise有三种状态: pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行。

1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列

  • promise 是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外)
  • 并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据
  • 代码风格,容易理解,便于维护
  • 多个异步等待合并便于解决
new Promise(
  function (resolve, reject) {
    // 一段耗时的异步操作
    resolve('成功') // 数据处理完成
    // reject('失败') // 数据处理出错
  }
).then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
)

promise是用来解决什么问题的

promise是用来解决两个问题的:

  • 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
  • promise可以支持多个并发的请求,获取并发请求中的数据
  • 这个promise可以解决异步的问题,本身不能说promise是异步的

处理异步请求,我们一般这样写
要求:先取得用户姓名,在根据姓名,取得用户的手机号

$.get('xxx.com/getUserName',function(data){
    $.get('xxx.com/getMobile',{user:data.userName},function(data){
    });
});

多个异步请求在一起,会出现嵌套深的情况,从而带来阅读和维护困难。

promise 本质上是分离了异步数据获取和业务逻辑,从而让开发人员能专注于一个事物,而不必同时考虑业务和数据。

promise有三个状态

1、pending[待定]初始状态
2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败

当promise状态发生改变,就会触发then()里的响应函数处理后续步骤;
promise状态一经改变,不会再变。
Promise对象的状态改变,只有两种可能:

  • 从pending变为fulfilled
  • 从pending变为rejected。
    这两种情况只要发生,状态就凝固了,不会再变了。

最简单的实例:

new Promise(resolve => {
  setTimeout(() => {
    resolve('hello')
  }, 2000)
}).then(res => {
  console.log(res)
})

js async/await

异步神器Async-await介绍与填坑
參考URL: https://www.jianshu.com/p/e511be9c1280

async/await 是ES7中被提实现异步操作的技术,相对比较新。

async - 定义异步函数

async 译:异步,是 Generator 函数的语法糖。该函数会返回一个promise对象,可以使用then方法添加回调函数,如果在函数内直接 return,Async会通过Promise.resolve()将其封装成Promise()对象,也可以通过.then添加回调函数

async function timeout(){
    return "helloworld";
}
console.log(timeout());
console.log("我在异步函数后面,会先执行谁呢");
// Promise { 'helloworld' }
// 我在异步函数后面,会先执行谁呢

作为一个关键字放在函数的前面,表示该函数是一个异步函数,意味着该函数的执行不会阻塞后面代码的执行 异步函数的调用跟普通函数一样。

可以看出执行顺序还是函数先执行,但是函数的返回结果是一个Promise对象,要获取Promise的返回值应该用then方法

async function timeout(){
    return "helloworld";
}
timeout().then((result)=>{
    console.log(result);
});
console.log("我在异步函数后面,会先执行谁呢");

// 我在异步函数后面,会先执行谁呢
// helloworld

此时先输出的就是后面的一串文字,说明异步函数的执行没有阻塞后面的代码执行。

async的内部实现原理就是如果该函数中有一个返回值,当调用该函数时,默认会在内部调用Promise.solve() 方法把它转化成一个Promise 对象作为返回,若函数内部抛出错误,则调用Promise.reject()返回一个Promise 对象

async function timeout1(flag){
    if(flag){
        return "hello world";
    }else{
        throw new Error("error!!");
    }
}

console.log(timeout1(true));
console.log(timeout1(false));
// Promise {<resolved>: "hello world"}
// Promise {<rejected>: Error: error!!...}

既然async返回的是一个Promise 对象,那么Promise 的所有用法他都可以用,如Promise.catch捕获异常等。

await - 暂停异步函数的执行

深入理解await与async
参考URL: https://www.cnblogs.com/jsgoshu/p/11444404.html

与线程阻塞不同的是,await 的阻塞发生在 async 函数内部,可以理解为一个异步的阻塞。

await命令后面的 Promise 对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到。

  • await的意思就是等待。它后面可以跟一个表达式。如果是值(如字符串、数字、普通对象等等)的话,返回值就是本身的值。
  • 不过最常用的是后面跟一个promise对象。await会等待这个promise的状态由pending转为fulfilled或者rejected。在此期间它会阻塞,延迟执行await语句后面的语句。

await即等待,用于等待一个Promise对象。它只能在异步函数 async function中使用,否则会报错。
它的返回值不是Promise对象而是Promise对象处理之后的结果。

await表达式会暂停当前 async function的执行,等待Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function,若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。​如果 await 操作符后的表达式的值不是一个 Promise,那么该值将被转换为一个已正常处理的 Promise。

如何从then()方法的api请求中获取数据,以便在函数外部处理数据

如何从then()方法的api请求中获取数据,以便在函数外部处理数据?
参考URL: https://cloud.tencent.com/developer/ask/sof/1086274

这应该在异步函数中完成。

工作中遇到常见问题总结

await is only valid in async function

const token = await hermez.CoordinatorAPI.getTokens()

运行报错:
SyntaxError: await is only valid in async function

问题分析:
这个错误的意思是await只能放到async函数内部,言下之意:

await必须放到函数里
函数必须有async修饰符

参考

[推荐-写的比较清晰]async/await
参考URL: https://www.jianshu.com/p/fb1da22f335d


网站公告

今日签到

点亮在社区的每一天
去签到