zoukankan      html  css  js  c++  java
  • js 异步解决方案

    js的异步请求历来被诟病,但是社区和规范一直也在努力,这里简单说下这些变化。

    ajax

    严格地说ajax属于与服务器交换数据的API,与异步并不完全相同。但对于早期的前端来说,异步的操作基本都是与ajax交涉的过程。

    2005年ajax-new-approach-web-application一文催生了ajax技术,随后各浏览器纷纷实现了XmlHttpRequest。其具有划时代的意义,为网页性能和用户体验带来了巨大的提升。下面是一个基于XmlHttpRequest对象实现的简单取数据的函数:

    var xhr = new XMLHttpRequest()
    xhr.onreadystatechange = function(){if(xhr.readyState === 4){
        if(xhr.status == 200){
    	console.log(xhr.responseText)
        }
    }}
    xhr.open('GET','https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState',true)
    xhr.send(null)
    

    可以看出这个对象具有浓浓的面向对象的风格,没有函数式编辑的优雅。目前作为XHR的替代api——fetch,则改正了这一股风气。

    jquery deffered

    这玩意已经退出历史舞台了,我差不多已经忘记了。但是17年去头条面试还居然问我$deffered是怎么实现的,要写代码。我表示很崩溃。

    promise

    promise 是es6的规范,它的规则如下:
    promise的参数是一个函数,这个函数执行时会被注入两个参数,resolve和reject,这两个函数会改变promise对象的状态,状态发生变化时则会执行相应的回调
    具体有三个状态:

    • pending
    • fullfilled
    • rejected

    状态转换规则如下:

    所以对于一个连续三次的异步操作,它的代码可能如下:

    function resolveNumAfter2S(x){
    	return new Promise(resolve=>{
    		setTimeout(()=>{resolve(x)}, 500)
    	})
    }
    
    resolveNumAfter2S(10)
    .then(x => {return resolveNumAfter2S(x+1)})
    .then(x => {return resolveNumAfter2S(x+2)})
    .then(x => {console.log(x)})
    

    promise 隐藏了中间一些抽象的处理,resolve,reject导致的状态变化以及它们的实现,then,catch的绑定都隐藏了,所以理解起来会有些困难,如果自己用js写一个类似的实现,则能容易理解它的功能,下面是一个小意思:

    const MyPromise = function(f){
    	f.bind(this, this._resolve.bind(this), this._reject.bind(this))()
    }
    
    MyPromise.prototype = Object.assign(MyPromise.prototype, {
    	status: 'pending',
    	_resolve: function (data) {
    		this.status = 'fullfilled';
    		this._then(data);
    	},
    	_reject: function (err) {
    		this.status = 'rejected';
    		this._catch(err);
    	},
    	then: function (f) {
    		this._then = f;
    		return this;
    	},
    	catch: function (f) {
    		this._catch = f;
    		return this;
    	}
    })
    
    
    function resolveAfter2s(x){
    	return new MyPromise((reslove,reject)=>{
    		setTimeout(()=>{
    			reject("err")
    		}, 2000)
    	})
    }
    
    var res = resolveAfter2s(10).then(x=>{
    	console.log(x)
    }).catch(err => {
    	console.log(err)
    })
    
    

    async await

    作为es7的终级异步解决方案,async/await的规则如下:

    • 使用async前缀定义的函数,会返回一个promise对象
    • await只能在async function 中使用
    • 遇到await 指令,异步代码的执行和同步代码一样,不会跳过

    对于一个简单的例子,大约很难体会它到底有什么用, 比如:

    function resolveNumAfter2S(x){
    	return new Promise(resolve=>{
    		setTimeout(()=>{resolve(x)}, 2000)
    	})
    }
    
    async function getNum(){
    	return await resolveNumAfter2S(1)
    }
    
    getNum().then(x=>{
    	console.log(x)
    })
    

    但考虑以下场景,就会发现其方便之处:

    function resolveNumAfter2S(x){
    	return new Promise(resolve=>{
    		setTimeout(()=>{resolve(x)}, 500)
    	})
    }
    // 假设你有一个需求,需要请求三个异步的数据,而每一步都要依赖上一步的数据,你完全可以以同步的代码体验去写代码:
    async function getNum(){
    	let a = await resolveNumAfter2S(6);
    	let b = await resolveNumAfter2S(a);
    	let c = await resolveNumAfter2S(b+a);
    
    	return a+b+c;
    }
    
    getNum().then(x=>{
    	console.log(x)
    })
    

  • 相关阅读:
    学习人人都是产品经理03
    Excel 自增
    axios中get/post请求方式
    vue本地跨域实现与原理
    于无声处听惊雷Deepin成长小记
    .NET桌面程序混合开发之三:WebView2与JS的深度应用
    跨平台系统的开发方案整理
    .NET桌面程序混合开发之二:在原生WinFrom程序中使用WebView2
    双系统升级Win11小记.md
    .NET桌面程序混合开发之一:Winform+H5,WebView2概览
  • 原文地址:https://www.cnblogs.com/magma/p/8297741.html
Copyright © 2011-2022 走看看