关于异步操作

作者: Gaarahan | 来源:发表于2018-05-19 20:20 被阅读13次

刚开始接触NodeJs便多次听到它是 单线程异步非阻塞IO模型 ,虽然看过好多例子,然而还是不怎么理解,借着一个BUG整理下思路。


问题

  • 尝试给一个本地的项目做一个简单的服务器时,用了如下的语句
    实际上用不着这么麻烦,这是我自己想到的处理方法
var backHeader = {
  'html' : {
    'content-type' : 'text/html',
    'charset':'utf8'
  },
  'css' : {
    'content-type' : 'text/css',
    'charset':'utf8'
  },
  'pic' : {
    'content-type' : 'image/jpeg',
    'charset':'utf8'
  },
  'js' : {
    'content-type' : 'application/x-javascript',
    'charset':'utf8'
  }
}

    ......
//对应不同的请求后缀名,给予不同的响应报文头
    var staticHead = "";

    if(url.endsWith('.jpg') || url.endsWith('.jpeg'))
      staticHead = backHeader['pic'];
    else if( url.endsWith('.css') ){
      staticHead = backHeader['css'];
    }
    else if(url.endsWith('.js')){
      staticHead = backHeader['js'];
    }
    else if(url.endsWith('.html')){
      staticHead = backHeader['html'];
    }
//读取请求的文件,并写入对应的报文头
    fs.readFile(file,function(err,data){
      if(err){
        ......
      }
      else{
        console.log(staticHead); //调试时加入的代码
        res.writeHeader(200,staticHead);
        res.write(data);
        res.end();
      }
    });

  • 但实际查看时,却发现有某些css文件的报文头出错:
    出错的报文头

原因

  • 尝试在控制台输出了每一次的响应报文头,发现输出是这样的:


分析这段代码的工作方式:

  • 分析传入的URL,并将对应的响应报文头存储到变量staticHead中
  • 读取URL请求的文件
  • 文件读取完毕后输出对应的响应报文头(调试代码)
  • 将读出来的文件内容写入到响应报文体中
  • 将响应报文发给浏览器来解析
虽然每个文件的响应报文头是没问题的,但存储响应报文头的变量staticHead只有一个, 这就是问题的所在:
  • 当接收到 /css/menu.css的请求时,分析了URL并得出了正确的结果存储在staticHead 中
  • 开始读取menu.css文件
  • 接收到请求 /js/menu_js.js,开始分析URL,将结果存储在staticHead中,此时menu.css文件还没有读取出来,但它的响应报文头已经被覆盖为了js文件的响应报文头
  • menu.css 文件读取成功,写入staticHead到响应报文,写入读取的数据到响应报文
  • 将响应报文发送给浏览器
  • 浏览器接收到menu.css文件的内容,并根据响应报文头将它解析为js文件

解决

  • 将分析URL的判断部分放到 fs.readFile(file,callback) 的回调函数部分中去
  • 利用NodeJs事件驱动的特性,只有当某个文件读取完成后,才会分析该文件的文件类型,写入到响应报文中发送给浏览器端,这个过程中,不会有其他对staticHead的操作,解决了问题

相关文章

  • 关于异步操作

    刚开始接触NodeJs便多次听到它是 单线程异步非阻塞IO模型 ,虽然看过好多例子,然而还是不怎么理解,借着一个B...

  • ES6 async 同步异步操作

    正如我之前的那篇关于Promise的介绍, async可以让你的异步操作变得更加简单。 异步操作 async函数返...

  • ES6 Primise异步编程

    异步操作流程化的手段 #Promise处理异步操作 Promise,使异步操作变得流程化的手段之一,例如“异步A ...

  • Promise--异步的解决方案

    Promise 对象是 JavaScript 的异步操作解决方案,为异步操作提供统一接口,使得异步操作具备同步操作...

  • .NET多线程(五)异步操作

    5、异步操作 5.1 异步操作基础 异步操作发展历史,APM模式,EAP模式,TPL模式 .NET 1.0 Sys...

  • Future

    juc.Future:Java异步操作结果 Future:Netty异步操作结果 Promise:可设置结果的异步...

  • ajax中的同步异步操作

    关于ajax中的同步异步操作 关于ajax中的同步异步经常不知道他的区别在哪里,看一一些其他的文章和帖子以后才总结...

  • Android AsyncTask基础

    AsyncTask是Android为了简化异步操作而封装的异步任务操作抽象类。当我们需要在程序中执行耗时的异步操作...

  • IOS多线程总结

    目录 简述 NSThread GCD操作与队列异步操作并行队列同步操作并行队列同步操作串行队列异步操作串行队列队列...

  • 异步编程方法

    前言 同步与异步最直观的理解:等到操作执行完成才返回执行结果的是同步操作;反之,则是异步操作 传统的异步编程方法:...

网友评论

    本文标题:关于异步操作

    本文链接:https://www.haomeiwen.com/subject/upjadftx.html