异步相关

2022-03-10  本文已影响0人  我家有个王胖胖

一:同步异步
XmlHttpRequest:

let url = 'static/a.json';
let xmlHttpRequest;
if(window.XMLHttpRequest){
    xmlHttpRequest = new XMLHttpRequest();
}else{//兼容旧版本
    xmlHttpRequest = new ActiveXObject('Microsoft.XMLHTTP')
}
xmlHttpRequest.open('GET',url,true);
xmlHttpRequest.send();
xmlHttpRequest.onreadystatechange = function() {
    if(xmlHttpRequest.readyState === 4 && xmlHttpRequest.status === 200){
       let obj = JSON.parse(xmlHttpRequest.responseText);
        console.log(obj);
    }
}
//{a: '我是A'}

Ajax原理:

//ajax的简单封装
let a = 'static/a.json';


function ajax(url,method,callback) {
    let xmlHttpRequest;
    if (window.XMLHttpRequest) {
        xmlHttpRequest = new XMLHttpRequest();
    } else {//兼容旧版本
        xmlHttpRequest = new ActiveXObject('Microsoft.XMLHTTP')
    }
    xmlHttpRequest.open(method, url, true);
    xmlHttpRequest.send();
    xmlHttpRequest.onreadystatechange = function () {
        if (xmlHttpRequest.readyState === 4 && xmlHttpRequest.status === 200) {
            let obj = JSON.parse(xmlHttpRequest.responseText);
            callback(obj)
        }
    }
}
ajax(a,'GET',res=>{
    console.log(res);//{a: '我是A'}
})

a->b->c
地狱回调问题:

ajax(a, 'GET', res => {
    console.log("aaa---", res);
    ajax(b, 'GET', res => {
        console.log("bbb---", res);
        ajax(c, 'GET', res => {
            console.log("ccc---", res);
        })
    })
})
aaa--- {a: '我是A'}
bbb--- {b: '我是B'}
ccc--- {c: '我是C'}

Promise解决回调地狱:

//基于上面的ajax的封装,我们进一步通过promise解决回调问题
//获取promise
function getPromise(url,method){
    return new Promise((resolve,reject)=>{
        ajax(url,method,res=>{
            resolve(res)
        })
    })
}
getPromise(a,"GET").then(res=>{
    console.log(res);
    return getPromise(b,'GET');
}).then(res => {
    console.log(res);
    return getPromise(c,'GET');
}).then(res=>{
    console.log(res);
})

案例:promise加载图片

const url = 'https://m.360buyimg.com/babel/jfs/t1/145983/4/5065/136336/5f313fcfEa5213607/170f4951fa1a845e.jpg.webp'
const url2 = 'https://img12.360buyimg.com/pop/s590x470_jfs/t1/136750/17/3835/71376/5f0434ecE1e5daa8d/7ab8f3deb1f8dd62.jpg.webp'
const wrapper = document.querySelector('#wrapper')
function loadImage(imgUrl) {
    let p = new Promise((resolve, reject) => {
        //let img = document.createElement("img");
        let img = new Image();
        img.onload = () => resolve(img);
        img.onerror = () => {
            let error = new Error("加载失败")
            reject(error);
        };
img.src = imgUrl;
        img.height = 200 
        img.width = 200 
    })
    return p;
}
loadImage(url).then(res=>{
    wrapper.appendChild(res)
    return loadImage(url2);
}).then(res=>{
    wrapper.appendChild(res)
}).catch(err=>{
    console.log(err.error,message);
})

效果:

promise加载图片.png
Promise的静态方法
①Promise.resolve
②Promise.reject
③Promise.all
④Promise.race
Promise.all():Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。
//上传图片
let imgArr = ['https://m.360buyimg.com/babel/jfs/t1/145983/4/5065/136336/5f313fcfEa5213607/170f4951fa1a845e.jpg.webp', 'https://img12.360buyimg.com/pop/s590x470_jfs/t1/136750/17/3835/71376/5f0434ecE1e5daa8d/7ab8f3deb1f8dd62.jpg.webp'];
let pushArr = [];
imgArr.forEach(item => {
    pushArr.push(new Promise((resolve, reject) => {
        resolve(item)//模拟上传后端
    }))
})
Promise.all(pushArr).then(result=>{
    console.log(result);
    console.log('图上上传成功');
})

效果:


Promise.all().png

Promise.race():顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

let url = 'https://m.360buyimg.com/babel/jfs/t1/145983/4/5065/136336/5f313fcfEa5213607/170f4951fa1a845e.jpg.webp'

function loadImg() {
    let p1 = new Promise((resolve, reject) => {
        let img = new Image();
        img.onload = function() {
            resolve('图片加载成功')
        }
        img.src = url;
    })
    return p1
}

function delay() {
    let p2 = new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('图片加载失败')
        }, 2000)
    })
    return p2
}
Promise.race([loadImg(), delay()]).then(result => {
    console.log(result);
})

Generator函数:
概念
    Generator 函数是 ES6 提供的一种异步编程解决方案。它既是一个生成器,也是一个状态机,内部拥有值及相关的状态,生成器返回一个迭代器 Iterator 对象,我们可以通过这个迭代器,手动地遍历相关的值、状态,保证正确的执行顺序。

特征
function 关键字与函数名之间有一个星号(ES6 没有规定,function 关键字与函数名之间的星号,写在哪个位置)
函数体内部使用 yield 表达式,定义不同的内部状态
调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是遍历器对象(Iterator Object)

function* sum(a) {
    let x = yield 1 + a;//6
    let y = yield 2 + x;//8
    return x + y;//16
}
//next()中参数会作为上一个yield表达式的返回值 
let sum1 = sum(5);
console.log(sum1.next());//{value: 6, done: false}
console.log(sum1.next(6));//{value: 8, done: false}
console.log(sum1.next(10));//{value: 16, done: done}

yield 表达式和 next() 方法
    由于 Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield 表达式就是暂停标志。

遍历器对象的next方法的运行逻辑:

遇到 yield 表达式,就暂停执行后面的操作,并将紧跟在 yield 后面的那个表达式的值,作为返回的对象的 value 属性值
下一次调用 next() 方法时,再继续往下执行,直到遇到下一个 yield 表达式.
如果没有再遇到新的 yield 表达式,就一直运行到函数结束,直到 return 语句为止,并将 return 语句后面的表达式的值,作为返回的对象的 value 属性值.
如果该函数没有 return 语句,则返回的对象的 value 属性值为 undefined
注意:

yield 表达式后面的表达式,只有当调用next()方法、内部指针指向该语句时才会执行.
yield 语句只能用于 function* 的作用域,如果 function* 的内部还定义了其他的普通函数,则函数内部不允许使用 yield 语句.
yield 语句如果参与运算,必须用括号括起来.

next() 方法的参数:
yield 表达式本身没有返回值,或者说总是返回undefined
next() 方法可以带一个参数,该参数会改变上一个yield表达式的返回值
Iterator:

Iterator.png
//模拟iterator的过程
function makeIterator(arr) {
    let nextIndex = 0;
    return {
        next() {
            return nextIndex < arr.length ? {value:arr[nextIndex++],done:false} : {value:undefined,done:true}
        }
    }
}
let it = makeIterator([1,2,3])
console.log(it.next());//{value: 1, done: false}
console.log(it.next());//{value: 2, done: false}
console.log(it.next());//{value: 3, done: false}
console.log(it.next());//{value: undefined, done: true}

原生具有iterator接口的数据结构


原生具有iterator接口的数据结构.png

对象使用for...of

let obj = {
        0:"我是0",
        1:"我是1",
        2:"我是2",
        length:3,
        //添加[Symbol.iterator]方法
        [Symbol.iterator] : function() {
            let _this = this;
            let index = 0;
            return {
                next:() => {
                    let value = _this[index];
                    let done = (index >= _this.length);
                    index++;
                    return {value,done}
                }
            }
        }
    };

    //咱们来for...of一下
    for(let v of obj){
        console.log(v);
    }
    //结果:"我是0"
    //      "我是1"
    //      "我是2"

Module:
AMD,CMD,CommonJS,ES6的区别

上一篇下一篇

猜你喜欢

热点阅读