专栏首页达达前端【面试Vue全家桶】vue前端交互模式-es7的​语法结构?async/await

【面试Vue全家桶】vue前端交互模式-es7的​语法结构?async/await

作者 | Jeskson

掘金 | https://juejin.im/user/5a16e1f3f265da43128096cb

2020.1.12

前端发请求,调用后端接口,来获取特定格式的数据,老板问了,你会前后端交互模式吗?vue的那种。异步接口调用,常常使用到的语法,promise的概念是什么呢?调用接口的方式,第一种为,fetch进行接口调用,第二种为,axios进行接口的调用。

es7的语法结构?async/await方式调用接口,基于不同接口的调用方式来实现案例。

让我们了解一下前后端的交互模式,学习一下promise的语法,来回答面试官的问题,基于promise来实现异步调用,就算你会promise?那你了解fetch用法和async/await用法吗?处理异步调用接口的方式。

网上一图,回调地狱:看到晕,使代码难以理解和维护。

前后端的交互是什么

前后端的交互就是前端的浏览器去调用后端的接口,拿到后端的数据,在做前端的处理,进行渲染。客户端与服务器的通信模式,前后端交互,调用接口的方法,第一种,原生的ajax,第二种,基于jquery的ajax,第三种,基于fetch,第四种,基于axios。

前端是通过请求地址向后端发送请求的,标准的url格式是什么样的呢?

格式如下:

schema://host:port/path?query#fragment

第一个schema为协议,比如http,https,ftp等,第二个,host为域名或者ip地址,第三个port为端口,http默认为80端口,是可以省略的,第四个path为路径,比如/index,第五个query为查询参数,比如name=dada&age=12,第六个fragment为锚点,哈希Hash,是用于定位页面的某个位置。

符合规则的url有哪些是正确的呢?

http://www.dada.cnhttp://www.dada.cn/index/dadahttp://www.dada.cn/index/dada?name=dadahttp://www.dada.cn/index/dada?name=dada#theme

新型的url地址,restful形式的。HTTP的请求方式,第一种,使用GET为查询,第二种,使用POST为添加,第三种,使用PUT为修改,第四种,使用DELETE为删除。

符合规则的url地址:

http://www.dada.com/index GEThttp://www.dada.com/index POSThttp://www.dada.com/index/1 PUThttp://www.dada.com/index/2 DELETE

promise对象

promise用于表示一个异步操作的最终完成(或失败),以及结果值。

Promise对象有以下两个特点

对象的状态不受外界影响

一旦状态改变,就不会再变,任何时候都可以得到这个结果

constpromise1 =newPromise(function(resolve, reject){ setTimeout(function(){ resolve('foo'); },300);});promise1.then(function(value){console.log(value);// expected output: "foo"});console.log(promise1);// expected output: [object Promise]

语法:

newPromise(function(resolve, reject){...}/* executor */);

因为 Promise.prototype.then 和 Promise.prototype.catch 方法返回promise 对象, 所以它们可以被链式调用。

promise用法

promise是什么呢?它是用于异步计算,将异步操作队列化,按照期望的顺序执行,返回符合预期的结果,可以在对象之间传递和操作promise。

创建promise

constda =newPromise((resolve, reject) =>{// resolve(someValue); // fulfilled// reject("failure reason"); // rejected});

functionda(url){returnnewPromise((resolve, reject) =>{constxhr =newXMLHttpRequest(); xhr.open("GET", url); xhr.onload =()=>resolve(xhr.responseText); xhr.onerror =()=>reject(xhr.statusText); xhr.send(); });};

简单的实例

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

异步操作,事件监听

document.getElementById('#start').addEventListener('click',start,false);functionstart(){// 响应事件,进行相应的操作}//jquery on 监听$("#start").on("click", start)

回调

$.ajax(url, { success(res) { }})// 在页面加载完毕后回调$(function(){// 页面结构加载完成})

在JavaScript中,异步情况,第一种为定时任务,第二种为ajax,第三种事件函数。

newPromise(function(resolve, reject){ resolve('成功')// 数据处理完成// reject('失败') // 数据处理出错}).then((res) =>{console.log(res)},// 成功(err) => {console.log(err)}// 失败)

异步编程与promise

$.ajax({

url: '',

success: function(data) {

console.log(data)

}

});

index.js

constexpress =require('express')constapp = express()constbodyParser =require('body-parser')// 处理静态资源app.use(express.static('public'))// 处理参数app.use(bodyParser.json());app.use(bodyParser.urlencoded({extended:false}));// 设置允许跨域访问服务app.all("*",function(req,res,next){ res.header("Access-Control-Allow-Origin","*"); res.header("Access-Control-Allow-Methods","PUT,GET,POST,DELETE,OPTIONS"); res.header("Access-Control-Allow-Headers","X-Requested-With"); res.header("Access-Control-Allow-Headers","Content-Type"); next();});// 路由app.get('/data', (req,res) => { res.send("hello world!")})// 启动监听app.listen(3000, () => {console.log("runing...")})

异步编程,多次异步调用,结果顺序结果不确定

promise是异步编程的一种解决方案,从语法上来讲,promise是一个对象,从它可以获取异步操作的消息。使用promise的好处有哪些呢?

它可以避免多层异步调用嵌套问题(回调地狱),promis对象提供了简洁的api,使得控制异步操作更加容易。回调地狱,多层嵌套请求问题,请求接口调用后台数据,有两种可能性,一种为成功回调,一种为失败回调,成功后写一下成功后的操作代码,失败后也要写一下失败后的操作代码。

在JavaScript中的世界里,所有的代码都是单线程执行的。因为这个缺点,所以会导致在JavaScript中的所有网络操作,浏览器事件,都必须是异步执行的,异步执行可以用回到函数实现。

functioncallback(){console.log("dada");}console.log("dada setTimeout()");setTimeout(callback,1000);// 1秒后调用callback函数

注意,异步操作会在将来某个时间点触发一个函数调用。

ajax的经典异步操作

request.onreadystatechange = function() {

if(request.readyState === 4) {

if(request.status === 200) {

return success(request.responseText);

}else{

return fail(request.status);

}

}

}

'usestrict';

new Promise(function() {} );

// 直接运行测试:

console.log('支持Promise!');

如果同时发送多个ajax的请求,返回来的结果是不确定的,要想返回的结果顺序确定下来,就必须进行嵌套,如果嵌套就会有回调地狱的问题,这样导致的代码可读性就会降低,所以就有promise语法来解决这一回调地狱的问题。

所以promise的出现的好处就是为了解决地狱回调,可以避免嵌套问题,和简洁的代码结构,可读性增强。

console.log(typeofPromise)

示例

letda =newPromise(function(resolve, reject){// 当异步代码执行成功时,会调用 resolve(...)// 当异步代码失败时, 会调用 reject(...)//使用setTimeout(...)来模拟异步代码setTimeout(function(){ resolve("成功!"); },250);});da.then(function(res){//res的值是上面调用resolve(...)方法传入的值.console.log("dada"+ res);});

promise的基本用法

首先实例化promise对象,构造函数中传递函数,该函数中用于处理异步任务,有两个参数,resolve和reject用于处理成功和失败的两种情况,并通过p.then获取处理结果。

then()方法返回一个promise:

constda =newPromise(function(resolve, reject){ resolve('da!');});da.then(function(value){console.log(value);// expected output: "da!"});

语法

p.then(onFulfilled[, onRejected]);

p.then(value => {

// fulfillment

}, reason => {

// rejection

});

var dada = new Promise((resolve, reject) => {

resolve('成功!');

// or

// reject(new Error("出错了!"));

});

dada.then(value => {

console.log(value); // 成功!

}, reason => {

console.error(reason); // 出错了!

});

catch()方法返回一个promise,并且处理拒绝的情况

p.catch(onRejected);p.catch(function(reason){// 拒绝});

finally()方法返回一个promise,在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。

p.finally(onFinally);p.finally(function(){// 返回状态为(resolved 或 rejected)});

newPromise(resolve=>{ setTimeout(()=>{ resolve('hello') },2000) }).then(val=>{console.log(val)// 参数val = 'hello'returnnewPromise(resolve=>{ setTimeout(()=>{ resolve('world') },2000) }) }).then(val=>{console.log(val)// 参数val = 'world'})

代码例子:

varp =newPromise(function(resolve, reject){// 成功回调 resolve()// 失败回调 reject()});p.then(function(ret){// resolve得到正常的结果},function(ret){// reject得到错误的结果});

resolve作用为将promise对象的状态从“未完成”变成为“成功”,即是从Pending变为resolved,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去,而reject的作用是将promise对象的状态从“未完成”变成“失败”,就是从Pending变成rejected,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

promise有三种状态,第一种为Pending,待定,初始状态,第二种状态为fulfilled,实现,操作成功,第三种状态为rejected,被否决,操作失败。

当promise状态发生改变时,就会触发then()里面的响应函数处理,promise状态一旦改变,就不会再变了。所以promis对象的状态改变有两种情况,第一种,从pending变为fulfilled,第二种为,从pending变为rejected。

基于promise处理ajax请求,处理原生ajax

functionqueryData(url){returnnewPromise(function(resolve,reject){varxhr =newXMLHttpRequest(); xhr.onreadystatechange =function(){if(xhr.readyState !=4)return;if(xhr.status ==200) { resolve(xhr.responseText) }else{ reject('出错了'); } } xhr.open('get',url); xhr.send(null); })}

发送多个ajax请求

queryData()

.then(function(data){

return queryData();

})

.then(function(data){

return queryData();

})

.then(function(data){

return queryData();

});

// return 是新的promise对象

then参数中的函数返回值

第一种,返回promsie实例对象,返回的实例对象会调用下一个then

第二种,返回普通值,返回的普通值会直接传递给下一个then,通过then参数中函数的参数接收该值

promise常用的api

实例方法有三种,第一种,p.then()得到异步任务的正确结果,第二种,p.catch()获取异常信息,第三种,p.finally()成功与否都会执行。

queryData() .then(function(data){console.log(data); }) .catch(function(data){console.log(data); }) .finally(function(){console.log('finished');});

promise常用api-实例方法

functionda(){returnnewPromise(function(resolve, reject){ setTimeout(function(){// resolve(123);reject('error'); },100);})}da() .then(function(data){console.log(data) }) .catch(function(data){console.log(data) }) .finally(function(){console.log('dada') });

da().then(function(data){console.log(data)},function(data){console.log(data)}).finally(function(){console.log('dada')});

对象方法

promise.all()并发处理多个异步任务,所有任务都执行完成才能得到结果

promise.race()并发处理多个异步任务,只要有一个任务完成就能得到结果

Promise.all([p1,p2,p3]).then(result) => {console.log(result);})Promise.race([p1,p2,p3]).then(result) => {console.log(result);})

代码:

functionqueryData(url){returnnewPromise(function(resolve, reject){varxhr =newXMLHttpRequest(); xhr.onreadystatechange =function(){if(xhr.readyState !=4)return;if(xhr.readyState ==4&& xhr.status ==200) {// 处理正常的情况resolve(xhr.responseText); }else{// 处理异常情况reject('服务器出错'); }; xhr.open('get',url); xhr.send(null); }); }varp1 = queryData(url);varp2 = queryDate(url1);Promise.all([p1,p2]).then(function(result){console.log(result)})

在promise中常用到回调函数延时绑定,返回值,错误冒泡。

constpromise =newPromise((resolve, reject) =>{console.log(1) resolve()console.log(2)})promise.then(()=>{console.log(3)})console.log(4)VM49:21VM49:42VM49:94VM49:73undefined

其中,promise构造函数是执行同步的作用,promise.then是执行异步函数的操作。

letpro =newPromise(resolve=>{ setTimeout(()=>{ resolve('hello world') },2000) }) setTimeout(()=>{ pro.then(value=>{console.log(value)// hello world}) },2000)

接口调用fetch的用法

fetch的概述,它更加简单的数据获取方式,功能更加强大,更加灵活,基于promise实现的。

语法结构:

fetch(url).then().then()....catch()

fetch的基本用法

fetch('/da').then(data=>{returndata.text();}).then(ret={console.log(ret);});

text()方法属于fetchapi中的一部分,它返回一个promise实例对象,用于获取后台返回的数据。

fetch请求参数

method(string)

http请求方法,默认为GET,可以使用POST,PUT,DELETE

body(string)

http的请求参数

headers(object)

http的请求头

fetch('/da', { method;'get'}).then(data=>{returndata.text();}).then(ret=>{console.log(ret);});

GET请求方式的参数传递

fetch('/da?id=123').then(data=>{returndata.text();}).then(ret=>{console.log(ret);});fetch('/da/123', {method:'get'}).then(data=>{returndata.text();}).then(ret=>{console.log(ret);});

delete请求方式的参数传递

fetch('/da/123', {method:'delete'}).then(data=>{returndata.text();}).then(ret=>{console.log(ret);});

fetch请求参数的post请求方式的参数传递

fetch('/da', {method:'post',body:'name=dada',headers: {'content-Type':'application/x-www-form-urlencoded', } }).then(data=>{returndata.text(); }).then(ret=>{console.log(ret); });

post请求方式的参数传递

fetch('/da', {method:'post',body:JSON.stringify({name:'dada',age:12}) headers;{'Conent-Type':'application/json', } }).then(data=>{returndata.text(); }).then(ret=>{console.log(ret);});

fetch响应结果

响应数据格式

text()

将返回体处理成字符串类型

json()

返回结果和json.parse(presponseText)相同

接口调用axios用法

第三方的库,很强大,是一个局域promise用于浏览器和node.js的HTTP客户端。

它的特性,第一点是支持浏览器和node.js,第二点是支持promise,第三点,能够拦截请求和响应,第四点,可以自动转换json类型。

axios的基本用法

axios.get('/dada').then(ret=>{console.log(ret.data);});

axios的常用api

get,查询数据,post,添加数据,put,修改数据,delete,删除数据。

get传递参数,第一,通过url传递参数,第二种,通过params传递参数

axios.get('/da?id=123').then(ret=>{console.log(ret.data);})

restful传参

axios.get('/dada/123')

.then(ret=>{

console.log(ret.data)

})

axios.get('/da', {params: { id:123}}).then(ret=>{console.log(ret.data)})

delete传递参数

参数传递方式与get类似

axios.delete('/da?id=1)

.then(ret=>{

console.log(ret.data)

})

axios.delete('/da/2)

.then(ret=>{

console.log(ret.data)

})

axios.delete('/da', {

params: {

id:1

}

})

.then(ret=>{

console.log(ret.data);

})

post传递参数

axios.post('/da', { name;'dada',}).then(res=>{console.log(res.data)})

默认传递的是json格式的数据。

post传递参数,通过URLSearchParams传递参数

application/x-www-form-urlencoded

constparams =newURLSearchParams();params.append('param1','value1');params.append('param2','value2');axios.post('/api/da', params).then(res=>{console.log(res.data)})

put传递参数

参数传递方式与post类似

axios.put('/da/1', {name:'dada',}).then(res=>{console.log(res.data)})

axios的响应结果

data为响应回来的数据,headers为响应头信息,status为响应状态码,statusText响应状态信息。

axios.post('/da-json').then(res=>{

console.log(res)

})

axios的全局 配置

axios.default.timeout = 3000; // 超时时间

axios.default.baseURL = 'http...' // 默认地址

axios.default.headers['mytoken'] = 'xxxx' //设置请求头

// 配置请求的基准url地址axios.default.baseURL ='http://localhost:xxx/';axios.get('da-json').then(function(res){console.log(res.data.name);});

axios拦截器

axios.interceptors.request.use(function(config){//在拿过去发出之前进行一些信息设置returnconfig;},function(err){// 处理响应的错误信息});

在获取数据之前对数据做一些加工处理。

接口调用async/await用法

async/await是es7引入的语法,更加方便了异步操作。

asyncfunctionqueryData(id){constres =awaitaxios.get('/data');returnres;}queryData.then(res=>{console.log(res)})

async关键字用于函数上,await关键字用于async函数中。

asyncfunctionname([param[, param[, ... param]]]){ statements }name: 函数名称param: 要传递给函数的参数的名称statements: 函数体语句返回值: 返回的Promise对象会以asyncfunction的返回值进行解析或者以该函数抛出的异常进行回绝。

多个异步请求的async/await处理

asyncfunctionqueryData(id){constda1 =awaitaxios.get('/da1');constda2 =awaitaxios.get('/da2?name=dada');returnres;}queryData.then(res=>{console.log(res)})

出现了async/await之前,我们有三种异步书写我们的代码,第一,嵌套回调,第二,以promise为主的链式回调,使用generators。

async function dada(x) {

let a = 1;

return x+a;

}

undefined

dada(10);

Promise {<resolved>: 11}__proto__:

Promisecatch: ƒ catch()constructor:

ƒ Promise()finally: ƒ finally()then:

ƒ then()Symbol(Symbol.toStringTag):

"Promise"__proto__: Object[[PromiseStatus]]:

"resolved"[[PromiseValue]]:

11

await只能在async函数内部使用,用在普通函数里就会报错。async/await实际上是Generator的语法糖。async关键字代表后面的函数中有异步操作,await表示等待一个异步方法执行完成。async 函数返回一个Promise对象,因此 async 函数通过 return 返回的值,会成为 then 方法中回调函数的参数。

await 就是异步等待,它等待的是一个Promise,async函数调用不会造成代码的阻塞,但是await会引起async函数内部代码的阻塞。

带async关键字的函数,是声明异步函数,返回值是promise对象

asyncfunctiontest(){return'da'}test();返回值为Promise{:"da"}。

宏任务和微任务都是队列

宏任务有script、setTimeout、setInterval等

微任务有Promise.then,catch,finally,process.nextTick等

参考地址

https://www.liaoxuefeng.com/wiki/1022910821149312/1023024413276544

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【微信小程序】如何获取用户绑定手机号

    达达前端
  • 微信小程序高级基础

    小程序是什么呢?小程序是一种不需要下载安装就可以使用的应用,它实现了应用"触手可及"的梦想,用户扫一扫或者搜一下就可以打开应用,也体现了龙哥"用完即走"的理念,...

    达达前端
  • ES6基础入门之let、const

    首先呢?欢迎大家来学习ES6入门基础let,const的基础知识内容。初始ECMA Script6。

    达达前端
  • AngularJS 中的Promise --- $q服务详解

    先说说什么是Promise,什么是$q吧。Promise是一种异步处理模式,有很多的实现方式,比如著名的Kris Kwal's Q还有JQuery的Deffe...

    用户1154259
  • ES6语法基础之变量解构赋值(数组)

    ES6变量解构赋值,看下数组与es5等区别,ES6的新特性大大节省了代码量,使代码可读性大大提高!

    十月梦想
  • 数组的一些方法

    天天_哥
  • ES6 小结(前端开发js技术进阶提升总结)

    es6中有很多特性,使javascript语法更加丰满,总结一波常用的es6知识点。

    用户1272076
  • 用黑客的思维 做中国最好的网络安全产品

    第五届“科技新浙商”年度人物前不久揭晓并颁奖,10位新一代浙商上榜,亮相经济大舞台。 这些70后主导的年轻、充满创业梦想的企业家们,大多来自新能源、新材料、信息...

    安恒信息
  • 将MySQL去重操作优化到极致之三弹连发(二):多线程并行执行

            上一篇已经将单条查重语句调整到最优,但该语句是以单线程方式执行。能否利用多处理器,让去重操作多线程并行执行,从而进一步提高速度呢?比如我的实验环...

    用户1148526
  • NodeJs-全局变量

    efonfighting

扫码关注云+社区

领取腾讯云代金券