zoukankan      html  css  js  c++  java
  • 强大的promise

    这个玩意叫做普罗米修斯,希腊神话的盗火英雄
    promise只用来包装异步函数,同步的会搞乱执行顺序,生产BUG

    // 如何使用
    function pro(){  
       return new Promise(function(resolve,reject){
          setTimeout(function(){
              var num = parInt(Math.random()*10);
              if(num>5){ 
                 resolve(num) 
                 // 这个可以写成
                 // return  Promise.resolve(num)
              }else{ 
                 reject(num) 
                 // 这个可以写成
                 // return  Promise.reject(num)
              } 
          },5000)
       })
    }
    // pro()这个返回的是一个pending的Promise对象
    // Promise可以被then启动,参数有两个,跟new的时候对应也是两个
    // new的时候第一个参数传递成功,then的时候第一个参数接受成功
    // new的时候第二个参数传递失败,then的时候第二个参数接受失败
    pro().then((res)=>{ ... },(error)=>{ ... })
    

    这个api是有固定写法的,用来把回调的异步函数转成链式的异步函数
    先看看传统的回调型异步函数

    function ajax1(){
       ajax({
           sucess:function(res1){
               //回调ajax2,或者直接把第二个ajax写在这里面
               ajax2(res1)
           }
       })
    }
    function ajax2(res1){
       ajax({
           sucess:function(res2){
               ...
           }
       })
    }
    ajax1()
    

    Promise写法

    function ajax1(){  
       return new Promise((resolve,reject)=>{
          ajax({
             sucess:function(res1){
               //回调ajax2,或者直接把第二个ajax写在这里面
               resolve(res1)
             }
          })
       }
    }
    function ajax2(){  
       return new Promise((resolve,reject)=>{
          ajax({
             sucess:function(res2){
               //回调ajax2,或者直接把第二个ajax写在这里面
               resolve(res2)
             }
          })
       }
    }
    ajax1().then((res1)=>{
       return ajax2(res1)
    }).then((res2)=>{
       ...
    })
    

    promise.resolve

    let res = Promise.resolve("123")
    res.then(res=>{ console.log(res) })
    

    promise.reject

    let res = Promise.reject("123")
    res.then(res=>{ console.log(res) })
    

    Promise.all
    这个使用在几个异步函数需要同时请求但是相互不关联的情况
    常用来作为初始化加载使用

    Promise.all([promise1, promise2, promise3]).then((values) => {
      console.log(values);
    },(error)=> {
      console.log(error)
    });
    // 如果上面几个promise函数没有全部返回成功,就会指向error
    

    看了上面的写法觉得也不过如此是吧,有没有改变,代码还变多了,我也是这么觉得的,直到看到Promise配合async使用

    async
    这个是Generator函数的语法糖
    什么是语法糖,就是更简易的使用,二次封装
    什么是Generator函数,这个是es6的api,还没被人知道就被他的语法糖async给抢了头条,所以不管,知道语法糖async怎么用就行

    任何函数都可以在前面加上单词async把函数升级成异步管理函数
    async只能在该函数的作用域里使用,如果是函数里的函数就得再写一次async了
    async要跟await配合使用,否则没有存在意义
    await要连接一个promise函数,primise要是一个异步函数
    这几个点不遵守肯定会有一些执行顺序等等的BUG

    function ajax1(){  
       return new Promise((resolve,reject)=>{
          ajax({
             sucess:function(res1){
               //回调ajax2,或者直接把第二个ajax写在这里面
               resolve(res1)
             }
          })
       }
    }
    function ajax2(opt){  
       return new Promise((resolve,reject)=>{
          ajax({
             sucess:function(res2){
               //回调ajax2,或者直接把第二个ajax写在这里面
               resolve(res2)
             }
          })
       }
    }
    async function init(){
       var res1 = await ajax1()
       var opt = res1 + 1; //模拟正常的方法什么的
       var res2 = await ajax2(opt)
    }
    init() 
    

    上面的代码如果是同步代码我们是很好理解的,但是因为是异步的,就不好理解了,正常来说因为ajax1和ajax2是异步的,res1和res2只会拿到undefined,这种运行顺序根本巅峰了对异步的理解,你确定这样的代码执行下来没问题?
    有没有问题可以自己试试

    async错误处理

    // 统一处理
    async function init(){
       try{
          var aa = await A()
          var bb = await B()
       }catch(err) {
          console.log(err)  
       }
    }
    
    // 单独处理
    async function init(){
       const [err, data] = await A().then(data => [null, data]).catch(err => [err, null])
       const [err, data] = await B().then(data => [null, data]).catch(err => [err, null])
    }
    
    // 上面的优化写法
    // 抽离成公共方法
    const awaitWrap = (promise) => {
      return promise
       .then(data => [null, data])
       .catch(err => [err, null])
    }
    async function init(){
       const [err, data] = await awaitWrap(A())
       const [err, data] = await awaitWrap(B())
    }
    

    如何理解async呢
    我们可以认为await阻塞了线程,如果有了解过java,在java里有个yeild的方法,这个方法就是await的语法糖,这个API让异步变成了同步,让代码更加的好理解

    做一个网络测速
    网络测速的前提是服务器超大的带宽
    原理是让前端递归去获取服务器的图片获得下载的网速,再把图片转base64递归上传获得上传的网速,我做了五个实验

    第一个

    var index = 10;
    function yi() {
        var start = new Date().getTime()
        var img = document.createElement("img");
        var num = Math.random()
        img.src = './img/xxx.png?num=' + num;
        img.onload = function (res){
            var end = new Date().getTime()
            console.log("递归----"+(end-start))
            index--;
            if(index!=0){
                yi()
            }
        }
    }
    yi()
    

    第二个

    var index = 10;
    var promiseArr = [];
    function getImg() {
    return new Promise(function (resolve, reject) {
        var start = new Date().getTime()
        var img = document.createElement("img");
        var num = Math.random()
        img.src = './img/girs.png?num=' + num;
        img.onload = function (res){
    	var end = new Date().getTime()
    	console.log("Promise.all----"+(end-start))
    	resolve(end-start);
        }
    })
    }
    function er() {
       for(var i=0;i<10;i++){
         promiseArr.push(getImg())
       }
       Promise.all(promiseArr).then()
    }
    er()
    

    第三个

    function getImg() {
       return new Promise(function (resolve, reject) {
    	var start = new Date().getTime()
    	var img = document.createElement("img");
    	var num = Math.random()
    	img.src = './img/girs.png?num=' + num;
    	img.onload = function (res){
    	    var end = new Date().getTime()
    	    console.log("10次await-----"+(end-start))
    	    resolve(end-start);
    	}
       })
    }
    async function san() {
       var allTime = 0;
       allTime += await getImg();
       allTime += await getImg();
       allTime += await getImg();
       allTime += await getImg();
       allTime += await getImg();
       allTime += await getImg();
       allTime += await getImg();
       allTime += await getImg();
       allTime += await getImg();
       allTime += await getImg();
    }
    san()
    

    第四个

    function getImg() {
       return new Promise(function (resolve, reject) {
    	var start = new Date().getTime()
    	var img = document.createElement("img");
    	var num = Math.random()
    	img.src = './img/girs.png?num=' + num;
    	img.onload = function (res){
    		var end = new Date().getTime()
    		console.log("for(x){await x}-----"+(end-start))
    		resolve(end-start);
    	}
       })
    }
    async function si() {
       var arr = []
       for(var i=0;i<10;i++){
    	arr.push(getImg())
       }   
       for (const x of arr){
    	await x;
       }
    }
    si()
    

    第五个

    function getImg() {
       return new Promise(function (resolve, reject) {
    	var start = new Date().getTime()
    	var img = document.createElement("img");
    	var num = Math.random()
    	img.src = './img/girs.png?num=' + num;
    	img.onload = function (res){
    		var end = new Date().getTime()
    		console.log("for await(x){x}+-----"+(end-start))
    		resolve(end-start);
    	}
       })
    }
    async function wu() {
       var arr = []
       for (var i=0;i<10;i++){
    	arr.push(getImg())
       }
       for await(const x of arr){
    	x;
       }
    }
    wu()
    

    这五个代码的执行时间都不一样,为什么还得研究

    封装一个promise版本的ajax

    function ajax(url, method = 'get', param = {}) {
        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            const paramString = getStringParam(param);
            if (method === 'get' && paramString) {
                url.indexOf('?') > -1 ? url += paramString : url += `?${paramString}`
            }
            xhr.open(method, url);
            xhr.onload = function () {
                const result = {
                    status: xhr.status,
                    statusText: xhr.statusText,
                    headers: xhr.getAllResponseHeaders(),
                    data: xhr.response || xhr.responseText
                }
                if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
                    resolve(result);
                } else {
                    reject(result);
                }
            }
            // 设置请求头
            xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            // 跨域携带cookie
            xhr.withCredentials = true;
            // 错误处理
            xhr.onerror = function () {
                reject(new TypeError('请求出错'));
            }
            xhr.timeout = function () {
                reject(new TypeError('请求超时'));
            }
            xhr.onabort = function () {
                reject(new TypeError('请求被终止'));
            }
            if (method === 'post') {
                xhr.send(paramString);
            } else {
                xhr.send();
            }
        })
    }
    
    function getStringParam(param) {
        let dataString = '';
        for (const key in param) {
            dataString += `${key}=${param[key]}&`
        }
        return dataString;
    }
    
  • 相关阅读:
    PyQt作品 – PingTester – 多点Ping测试工具
    关于和技术人员交流的一二三
    Pyjamas Python Javascript Compiler, Desktop Widget Set and RIA Web Framework
    Hybrid Qt applications with PySide and Django
    pyjamas build AJAX apps in Python (like Google did for Java)
    PyQt 维基百科,自由的百科全书
    InfoQ:请问为什么仍要选择Java来处理后端的工作?
    Eric+PyQt打造完美的Python集成开发环境
    python select module select method introduce
    GUI Programming with Python: QT Edition
  • 原文地址:https://www.cnblogs.com/pengdt/p/12037983.html
Copyright © 2011-2022 走看看