async 和 await
- 参考:async/await基本理解及项目案例(结合Promise)
- async 修饰符,用于修饰函数,是函数返回一个Promise对象的resolve的值
- await 修饰符,只能用于 async 修饰函数内部,作用是获取Promise 中返回的内容,获取的是Promis函数中resolve或者reject的值如果await 后面并不是一个Promise 的返回值,则会按照同步程序返回值处理
function f1(){
return 'f1'
}
// 使用async关键词的函数会被包装,自动返回promise类型数据
async function f2(){
return 'f2'
// 等价于不加async关键字时
// return Promise.resolve('f2')
//return new Promise((resolve,reject) => {resolve('f2')})
}
function f3(){
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log('ff3')
resolve('f3')
},2000)
})
}
function f4(){
return Promise.reject('f4')
}
async function main(){
const c1 = await f1()
console.log(c1)
const resp = await f3()
console.log('------')
console.log(resp)
try {
var c = await f4()
}catch{
console.log('error')
}
}
const c1 = await f1()
console.log(c1)
const resp = await f3()
console.log('------')
console.log(resp)
try {
var c = await f4()
}catch{
console.log('error')
}
}
main()
// output
// f1
// ff3
// ------
// f3
// error
//下面是对 async 和 await 的Vue的实际运用
// hrrp.vue
'use strict'
import axios from 'axios'
import qs from 'qs'
axios.interceptors.request.use(config => {
// loading
return config
}, error => {
return Promise.reject(error)
})
axios.interceptors.response.use(response => {
return response
}, error => {
return Promise.resolve(error.response)
})
function checkStatus (response) {
// loading
// 如果http状态码正常,则直接返回数据
if (response && (response.status === 200 || response.status === 304 || response.status === 400)) {
return response
// 如果不需要除了data之外的数据,可以直接 return response.data
}
// 异常状态下,把错误信息返回去
return {
status: -404,
msg: '网络异常'
}
}
function checkCode (res) {
// 如果code异常(这里已经包括网络错误,服务器错误,后端抛出的错误),可以弹出一个错误提示,告诉用户
if (res.status === -404) {
alert(res.msg)
}
if (res.data && (!res.data.success)) {
alert(res.data.error_msg)
}
return res
}
export default {
post (data,url) {
return axios({
method: 'post',
url: url,
data: qs.stringify(data),
timeout: 10000,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}).then(
(response) => {
return checkStatus(response)
}
)
},
get (url, params) {
return axios({
method: 'get',
baseURL: 'https://cnodejs.org/api/v1',
url,
params, // get 请求时带的参数
timeout: 10000,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
}).then(
(response) => {
return checkStatus(response)
}
).then(
(res) => {
return checkCode(res)
}
)
}
}
// app.vue
export default {
getCode: 'http://127.0.0.1:8888/.....'
}
// auth.vue
import http from '../../utils/http'
import api from '../../utils/api'
methods: {
fetchData: async function () {
var that = this
var code = Store.fetchYqm();
let params = {
inviteCode: code
}
const response = await http.post(params,api.getCode)
var resJson = response.data;
}
}
关于跨域
- 关于跨域
- 同源限制
- 出现跨域问题是因为浏览器的同源策略,同源策略浏览器阻止一个域的脚本和另一个域的交互,所谓的同源是指 具有相同的协议、域名、端口
- 跨域就是同源中 出现不同 如 域名不同、主机不同、端口不同等,都会产生跨域问题
- 非同源限制
- 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
- 无法接触非同源网页的 DOM
- 无法向非同源地址发送 AJAX 请求
- 解决跨域
- 设置document.domain解决无法读取非同源网页的 Cookie问题
- 跨文档通信 API:window.postMessage()
- JSONP
- JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求
- 其原理是 通过使用
<script>
标签来规避浏览器的同源策略限制,实现跨域请求数据
- document.domain
/*
* 设置document.domain解决无法读取非同源网页的 Cookie问题
*/
document.domain = '要跨域的域名';
- window Api
/*
* 跨文档通信 API:window.postMessage()
*/
// 父窗口打开一个子窗口
var openWindow = window.open('http://test2.com', 'title');
// 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');
// 监听 message 消息
window.addEventListener('message', function (e) {
console.log(e.source); // e.source 发送消息的窗口
console.log(e.origin); // e.origin 消息发向的网址
console.log(e.data); // e.data 发送的消息
},false);
- jqeury Jsonp
/*
* JSONP
* jquery
*/
$.ajax({
type: "get",
async: false,
url: "ajax.ashx",
dataType: "jsonp",
jsonp: "callbackparam",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback)
jsonpCallback: "success_jsonpCallback",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
success: function (json) {
//*****
},
error: function () {
//****
}
});
- script书写
<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
// 处理服务器返回回调函数的数据
<script type="text/javascript">
function dosomething(res){
// 处理获得的数据
console.log(res.data)
}
</script>
// Vue
this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
}
关于宏任务和微任务
- 参考
- 宏任务
- 包括整体代码script,setTimeout,setInterval、I/O、UI 交互事件、setImmediate(Node.js 环境);
- 微任务
- Promise、MutaionObserver、process.nextTick(Node.js 环境)
- 注:new Promise中的代码会立即执行,then函数分发到微任务队列,process.nextTick分发到微任务队列Event Queue
setTimeout(function() {
console.log('宏任务setTimeout'); //先遇到setTimeout,将其回调函数注册后分发到宏任务Event Queue
//如果setTimeout设置时间,那它会先把函数放到宏任务Event Table,等时间到了再放入宏任务Event Queue里面
})
new Promise(function(resolve) {
console.log('微任务promise'); //new Promise函数立即执行
resolve(); //必须resolve执行才能执行then
}).then(function() {
console.log('微任务then'); //then函数分发到微任务Event Queue
})
console.log('主线程console');
- 执行顺序结果: 微任务promise、主线程console、微任务then、宏任务setTimeout
- 事件循环,宏任务,微任务的关系如图所示:
- 关于宏任务和微任务的一些题
console.log('1主线程'); //整体script作为第一个宏任务进入主线程
setTimeout(function() { //setTimeout,其回调函数被分发到宏任务Event Queue(执行规则:从上到下排序,先进先执行)中
console.log('2宏任务');
process.nextTick(function() {
console.log('3宏任务里面的微任务');
})
new Promise(function(resolve) {
console.log('4微任务');
resolve();
}).then(function() {
console.log('5微任务')
})
})
process.nextTick(function() { //process.nextTick()其回调函数被分发到微任务Event Queue中
console.log('6微任务');
})
new Promise(function(resolve) { //Promise,new Promise直接执行,输出7
console.log('7微任务');
resolve();
}).then(function() {
console.log('8微任务') //then被分发到微任务Event Queue中,排在process.nextTick微任务后面。
})
setTimeout(function() { //setTimeout,其回调函数被分发到宏任务Event Queue中,排在前面的setTimeout后面
console.log('9宏任务');
process.nextTick(function() {
console.log('10宏任务里面的微任务');
})
new Promise(function(resolve) {
console.log('11微任务');
resolve();
}).then(function() {
console.log('12微任务')
})
//执行结果: 1主线程、7微任务、6微任务、8微任务、2宏任务、4微任务、3宏任务里面的微任务、5微任务、
// 9宏任务、11微任务、10宏任务里面的微任务、12微任务
})
- async函数本事是同步的 不过 其会将返回结果包装到Promise中 所以也算是微任务吧
async function async1() {
console.log('async1 start')
new Promise(function(resolve){
console.log('async2')
resolve()
}).then(function(){
console.log('async1 end')
})
}
async1()
console.log('script end')
// 执行顺序是:async1 start –> async2 –> script end –> async1 end
声明:本文只用于个人学习,如发现存在错误可以评论,我将更改,如发现侵权,可以联系我,会立刻删除该文,谢谢