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;
    }
    
  • 相关阅读:
    SAP扫盲系列之二:SAP ABAP应用服务器的组成部分
    SAP扫盲系列之一:什么是SAP系统和应用服务器
    SAP CRM中间件下载时,为什么有时候会生成一个奇怪的BDOC容器
    SAP Cloud for Customer ABSL的一些优化
    How to test Delta download in CRM Side
    SAP CRM中间件下载时数据库表CRMATAB为空的处理方法
    如何关闭SAP CRM中间件的delta download方式
    SAP CRM Fiori应用冗余round trip的原因分析
    SAP CRM WebClient UI上以html格式显示note的问题讨论
    微信授权登录
  • 原文地址:https://www.cnblogs.com/pengdt/p/12037983.html
Copyright © 2011-2022 走看看