首页 > 技术文章 > 2019-6-21 解决异步的方式

wangshuai33 2019-06-21 14:13 原文

2019-6-21 解决异步的方式

1. callback

  • ajax异步请求

  1. //如何封装一个原生的ajax 
  2. function ajax(options)
  3. var data = options.data || {} 
  4. var url = options.url || ' ' 
  5. var method = options.method || 'get' 
  6. var success = options.success  
  7. var fail = options.fail 
  8. var dataType = options.dataType || 'text' 
  9. // 第一步  
  10. var ajax = new XMLHttpReques() 
  11. //由于post 和 get 请求的方式不一样 要区别开来 
  12. //method 统一转换成小写形式 
  13. method = method.toLowerCase() 
  14. if(method === 'get'){ 
  15. var arr = [] 
  16. for (var key in data){  
  17. var str = key + '=' + data[key];  
  18. arr.push(str) 

  19. if(arr.length){ 
  20. url += arr.join('&'

  21. // 第二步 
  22. ajax.open(method,url,true
  23. // 第三步 
  24. ajax.send() 
  25.  
  26. }else
  27. //post 请求 
  28. // 需要设置请求报文 
  29. ajax.open(method,url); 
  30. ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
  31. // 判断data send发送数据 
  32. if (data) { 
  33. // 如果有值 从send发送 
  34. ajax.send(data); 
  35. }else
  36. // 木有值 直接发送即可 
  37. ajax.send(); 


  38. // 第四步 
  39. ajax.onreadystatechange = function ()
  40. if (ajax.readyState == 4 && ajax.status == 200 || ajax.status == 304) { 
  41. var _data; 
  42. switch(datatype){ 
  43. case "json"
  44. _data = JSON.parse(ajax.responseText); // 此处_data 就是你指定的数据类型 
  45. break
  46. case "text"
  47. _data = ajax.responseText; 
  48. break

  49. success(_data); 
  50. }else
  51. fail(_data) 


  52.  

  53.  

总结 :success 和 fail 函数 都是 回调函数callback,通过callback把异步获取的数据请求出来

2. promise

使用回调函数当然可以很好的解决异步代码的问题,但是多层嵌套很容易使代码书写麻烦,维护麻烦

fs.readdir(source, function (err, files) {
  if (err) {
    console.log('Error finding files: ' + err)
  } else {
    files.forEach(function (filename, fileIndex) {
      console.log(filename)
      gm(source + filename).size(function (err, values) {
        if (err) {
          console.log('Error identifying file size: ' + err)
        } else {
          console.log(filename + ' : ' + values)
          aspect = (values.width / values.height)
          widths.forEach(function (width, widthIndex) {
            height = Math.round(width / aspect)
            console.log('resizing ' + filename + 'to ' + height + 'x' + height)
            this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
              if (err) console.log('Error writing file: ' + err)
            })
          }.bind(this))
        }
      })
    })
  }
})

基于三点规则来解决回调地狱

  1. 避免函数多层嵌套

  2. 模块化(职责单一)

  3. 处理问题简单

如何用 promise 封装原生的ajax

  • Promise是一个构造函数,自己身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样很眼熟的方法。

  • reject 和 resolve 也是一种回调 换句话来说就是用回调封装成一种promise 再解决回调多层的概念

  1. // 定义一个promise 函数 
  2. class Promise
  3. constructor(exepromise){ 
  4. // 初始化 state 状态  
  5. this.state = 'pedding' 
  6. this.sucValue = undefined 
  7. this.errValue = undefined 
  8. let resolve = (data) =>{ 
  9. if(this.state == 'pedding'){ 
  10. this.sucValue = data 
  11. this.state = 'resolve' 


  12. let reject = (err)=>{ 
  13. if(this.state == 'pedding'){ 
  14. this.state = 'reject' 
  15. this.errValue = err 


  16. try
  17. exepromise(resolve,reject) 
  18. }catch(err){ 
  19. reject(err) 


  20. then(toResolve,toReject){ 
  21. if(this.state == 'resovle'){ 
  22. toResolve(this.sucValue) 

  23. if(this.state == 'reject'){ 
  24. toReject(this.errValue) 

  25.  
  26. }  

  27.  
  28. var p = new Promise(function(resolve, reject)
  29. //做一些异步操作 
  30. setTimeout(function()
  31. console.log('执行完成'); 
  32. resolve('随便什么数据'); 
  33. }, 2000); 
  34. }); 
  35.  

3. async/await

  • async/await 是对 Promise 的优化: async/await是基于Promise的,是进一步的一种优化,不过在写代码时,Promise本身的API出现得很少,很接近同步代码的写法;

  • 同时也可以说是 async 函数是 Generator 的语法糖。

3.1 async 函数

  • function 函数前面加个 == async==

推荐阅读