范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

前端开发必会技巧收藏异步编程

  在我们的工作和学习当中,到处充满了异步的身影,到底什么是异步,什么是异步编程,为什么要用异步编程,以及经典的异步编程有哪些,在工作中的场景又有什么,我们一点点深入的去学习。
  什么是异步编程?
  有必要了解一下,什么是异步编程,为什么要异步编程。
  先说一个概念异步与同步。介绍异步之前,回顾一下,所谓同步编程,就是计算机一行一行按顺序依次执行代码,当前代码任务耗时执行会阻塞后续代码的执行。
  同步编程,即是一种典型的请求-响应模型,当请求调用一个函数或方法后,需等待其响应返回,然后执行后续代码。
  一般情况下,同步编程,代码按序依次执行,能很好的保证程序的执行,但是在某些场景下,比如读取文件内容,或请求服务器接口数据,需要根据返回的数据内容执行后续操作,读取文件和请求接口直到数据返回这一过程是需要时间的,网络越差,耗费时间越长。
  如果按照同步编程方式实现,在等待数据返回这段时间,JavaScript是不能处理其他任务的,此时页面的交互,滚动等任何操作也都会被阻塞,这显然是及其不友好,不可接受的,而这正是需要异步编程大显身手的场景。
  我们想通过Ajax请求数据来渲染页面,这是一个在我们前端当中很常见渲染页面的方式。基本每个页面都会都这样的过程。在这里用同步的方式请求页面会怎么样?浏览器锁死,不能进行其他操作。而且每当发送新的请求,浏览器都会锁死,用户体验极差。
  在浏览器中同步执行将会是上面的这个样子,任务1做完才能做任务2,任务2做完才会做任务3。这里面体现出同步编程的有序的特点。只能1,2,3不能1,3,2。但是我们的代码逻辑中可以存在多任务同时执行的过程。在我们生活中,煮饭和烧水可以同时去做,同样在我们编程中也需要这样的逻辑。
  在计算机中有多线程的概念,什么意思呢,每一个线程做一件事,像下面这样。
  在不同的线程中可以执行不同的任务。
  但是我们的JavaScript是单线程的,这里的单线程,强调的执行线程是单线程。后面也是有线程池的,线程以及线程池的概念在这里就不多说了。想了解的同学可以看看操作系统相关书籍。
  JavaScript语言执行环境是单线程的,单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。
  但是我们也需要类似多线程机制的这种执行方式。但是JavaScript还是单线程的,我们需要异步执行,异步执行会使得多个任务并发执行。
  并行与并发。前文提到多线程的任务可以并行执行,而JavaScript单线程异步编程可以实现多任务并发执行,这里有必要说明一下并行与并发的区别。
  并行,指同一时刻内多任务同时进行。边煮饭,边烧水,可以同时进行并发,指在同一时间段内,多任务同时进行着,但是某一时刻,只有某一任务执行。边吃饭边喝水,同一时间点只能喝水和吃饭。
  接下来说一说异步机制
  并发模型
  目前,我们已经知道,JavaScript执行异步任务时,不需要等待响应返回,可以继续执行其他任务,而在响应返回时,会得到通知,执行回调或事件处理程序。那么这一切具体是如何完成的,又以什么规则或顺序运作呢?接下来我们需要解答这个问题。回调和事件处理程序本质上并无区别,只是在不同情况下,不同的叫法。
  前文已经提到,JavaScript异步编程使得多个任务可以并发执行,而实现这一功能的基础是JavaScript拥有一个基于事件循环的并发模型。
  堆栈与队列
  介绍JavaScript并发模型之前,先简单介绍堆栈和队列的区别:
  堆(heap):内存中某一未被阻止的区域,通常存储对象(引用类型);
  栈(stack):后进先出的顺序存储数据结构,通常存储函数参数和基本类型值变量(按值访问);
  队列(queue):先进先出顺序存储数据结构。
  事件循环(EventLoop):JavaScript引擎负责解析,执行JavaScript代码,但它并不能单独运行,通常都得有一个宿主环境,一般如浏览器或Node服务器,前文说到的单线程是指在这些宿主环境创建单一线程,提供一种机制,调用JavaScript引擎完成多个JavaScript代码块的调度,执行(是的,JavaScript代码都是按块执行的),这种机制就称为事件循环(EventLoop)。
  JavaScript执行环境中存在的两个结构需要了解:
  消息队列(messagequeue),也叫任务队列(taskqueue):存储待处理消息及对应的回调函数或事件处理程序;
  执行栈(executioncontextstack),也可以叫执行上下文栈:JavaScript执行栈,顾名思义,是由执行上下文组成,当函数调用时,创建并插入一个执行上下文,通常称为执行栈帧(frame),存储着函数参数和局部变量,当该函数执行结束时,弹出该执行栈帧;
  注:关于全局代码,由于所有的代码都是在全局上下文执行,所以执行栈顶总是全局上下文就很容易理解,直到所有代码执行完毕,全局上下文退出执行栈,栈清空了;也即是全局上下文是第一个入栈,最后一个出栈。
  任务
  分析事件循环流程前,先阐述两个概念,有助于理解事件循环:同步任务和异步任务。
  任务很好理解,JavaScript代码执行就是在完成任务,所谓任务就是一个函数或一个代码块,通常以功能或目的划分,比如完成一次加法计算,完成一次ajax请求;很自然的就分为同步任务和异步任务。同步任务是连续的,阻塞的;而异步任务则是不连续,非阻塞的,包含异步事件及其回调,当我们谈及执行异步任务时,通常指执行其回调函数。
  事件循环流程
  关于事件循环流程分解如下:
  宿主环境为JavaScript创建线程时,会创建堆(heap)和栈(stack),堆内存储JavaScript对象,栈内存储执行上下文;
  栈内执行上下文的同步任务按序执行,执行完即退栈,而当异步任务执行时,该异步任务进入等待状态(不入栈),同时通知线程:当触发该事件时(或该异步操作响应返回时),需向消息队列插入一个事件消息;
  当事件触发或响应返回时,线程向消息队列插入该事件消息(包含事件及回调);
  当栈内同步任务执行完毕后,线程从消息队列取出一个事件消息,其对应异步任务(函数)入栈,执行回调函数,如果未绑定回调,这个消息会被丢弃,执行完任务后退栈;
  当线程空闲(即执行栈清空)时继续拉取消息队列下一轮消息(nexttick,事件循环流转一次称为一次tick)。
  使用代码可以描述如下:
  vareventLoop = [];
  var event;
  var i = eventLoop.length - 1; // 后进先出
  while(eventLoop[i]) {
  event = eventLoop[i--];
  if (event) { // 事件回调存在
  event();
  }
  // 否则事件消息被丢弃
  }
  这里注意的一点是等待下一个事件消息的过程是同步的。
  并发模型与事件循环
  varele = document.querySelector("body");
  function clickCb(event) {
  console.log("clicked");
  }
  function bindEvent(callback) {
  ele.addEventListener("click", callback);
  }
  bindEvent(clickCb);
  针对如上代码我们可以构建如下并发模型:
  如上图,当执行栈同步代码块依次执行完直到遇见异步任务时,异步任务进入等待状态,通知线程,异步事件触发时,往消息队列插入一条事件消息;而当执行栈后续同步代码执行完后,读取消息队列,得到一条消息,然后将该消息对应的异步任务入栈,执行回调函数;一次事件循环就完成了,也即处理了一个异步任务。
  JS 中异步有几种?
  JS中异步操作还挺多的,常见的分以下几种:
  setTimeout(setInterval)
  AJAX
  Promise
  Generator
  setTimeout
  setTimeout(
  function() {
  console.log("Hello!");
  },1000);
  setTimout(setInterval)并不是立即就执行的,这段代码意思是,等1s后,把这个function 加入任务队列中,如果任务队列中没有其他任务了,就执行输出"Hello"。
  varouterScopeVar;
  helloCatAsync();
  alert(outerScopeVar);
  functionhelloCatAsync() {
  setTimeout(function() {
  outerScopeVar = "hello";
  }, 2000);
  }
  执行上面代码,发现outerScopeVar 输出是undefined,而不是hello。之所以这样是因为在异步代码中返回的一个值是不可能给同步流程中使用的,因为console.log(outerScopeVar) 是同步代码,执行完后才会执行setTimout。
  helloCatAsync(function(result){
  console.log(result);
  });
  functionhelloCatAsync(callback) {
  setTimeout(
  function() {
  callback("hello")
  }
  , 1000)
  }
  把上面代码改成,传递一个callback,console输出就会是hello。
  AJAX
  varxhr = new XMLHttpRequest();
  xhr.onreadystatechange= function() {
  if ((xhr.status >= 200 && xhr.status < 300) ||xhr.status == 304 ) {
  console.log(xhr.responseText);
  } else {
  console.log( xhr.status);
  }
  }
  xhr.open("GET","url", false);
  xhr.send();
  上面这段代码,xhr.open中第三个参数默认为false 异步执行,改为true 时为同步执行。
  Promise规范简述
  promise是一个拥有then 方法的对象或函数。一个promise有三种状态pending, rejected, resolved状态一旦确定就不能改变,且只能够由pending状态变成rejected或者resolved状态,reject和resolved状态不能相互转换。
  当promise执行成功时,调用then方法的第一个回调函数,失败时调用第二个回调函数。promise实例会有一个then方法,这个then方法必须返回一个新的promise。
  基本用法
  //异步操作放在Promise构造器中
  constpromise1 = new Promise((resolve) => {
  setTimeout(() => {
  resolve("hello");
  }, 1000);
  });
  //得到异步结果之后的操作
  promise1.then(value=> {
  console.log(value, "world");
  },error =>{
  console.log(error, "unhappy")
  });
  异步代码,同步写法
  asyncFun()
  .then(cb)
  .then(cb)
  .then(cb)
  promise以这种链式写法,解决了回调函数处理多重异步嵌套带来的回调地狱问题,使代码更加利于阅读,当然本质还是使用回调函数。
  异常捕获
  前面说过如果在异步的callback函数中也有一个异常,那么是捕获不到的,原因就是回调函数是异步执行的。我们看看promise是怎么解决这个问题的。
  asyncFun(1).then(function(value) {
  throw new Error("出错啦");
  },function (value) {
  console.error(value);
  }).then(function(value) {
  },function (result) {
  console.log("有错误",result);
  });
  其实是promise的then方法中,已经自动帮我们trycatch了这个回调函数,实现大致如下:
  Promise.prototype.then= function(cb) {
  try{
  cb()
  }catch (e) {
  // todo
  reject(e)
  }
  }
  then方法中抛出的异常会被下一个级联的then方法的第二个参数捕获到(前提是有),那么如果最后一个then中也有异常怎么办。
  Promise.prototype.done= function (resolve, reject) {
  this.then(resolve, reject).catch(function (reason) {
  setTimeout(() => {
  throw reason;
  }, 0);
  });
  };
  asyncFun(1).then(function (value) {
  throw new Error("then resolve回调出错啦");
  }).catch(function (error) {
  console.error(error);
  throw new Error("catch回调出错啦");
  }).done((reslove, reject) => {});
  我们可以加一个done方法,这个方法并不会返回promise对象,所以在此之后并不能级联,done方法最后会把异常抛到全局,这样就可以被全局的异常处理函数捕获或者中断线程。这也是promise的一种最佳实践策略,当然这个done方法并没有被ES6实现,所以我们在不适用第三方Promise开源库的情况下就只能自己来实现了。为什么需要这个done方法。
  constasyncFun = function (value) {
  return new Promise(function (resolve, reject) {
  setTimeout(function () {
  resolve(value);
  }, 0);
  })
  };
  asyncFun(1).then(function(value) {
  throw new Error("then resolve回调出错啦");
  });
  (node:6312)UnhandledPromiseRejectionWarning: Unhandled promise rejection(rejection id: 1): Error: then resolve回调出错啦
  (node:6312)[DEP0018] DeprecationWarning: Unhandled promise rejections aredeprecated. In the future, promise rejections that are not handledwill terminate the Node.js process with a non-zero exit code
  我们可以看到JavaScript线程只是报了一个警告,并没有中止线程,如果是一个严重错误如果不及时中止线程,可能会造成损失。
  局限
  promise有一个局限就是不能够中止promise链,例如当promise链中某一个环节出现错误之后,已经没有了继续往下执行的必要性,但是promise并没有提供原生的取消的方式,我们可以看到即使在前面已经抛出异常,但是promise链并不会停止。虽然我们可以利用返回一个处于pending状态的promise来中止promise链。
  constpromise1 = new Promise((resolve) => {
  setTimeout(() => {
  resolve("hello");
  }, 1000);
  });
  promise1.then((value)=> {
  throw new Error("出错啦!");
  }).then(value=> {
  console.log(value);
  },error=> {
  console.log(error.message);
  return result;
  }).then(function() {
  console.log("DJL箫氏");
  });
  特殊场景
  当我们的一个任务依赖于多个异步任务,那么我们可以使用Promise.all,当我们的任务依赖于多个异步任务中的任意一个,至于是谁无所谓,Promise.race
  上面所说的都是ES6的promise实现,实际上功能是比较少,而且还有一些不足的,所以还有很多开源promise的实现库,像q.js等等,它们提供了更多的语法糖,也有了更多的适应场景。
  核心代码
  vardefer = function () {
  var pending = [], value;
  return {
  resolve: function (_value) {
  value = _value;
  for (var i = 0, ii = pending.length; i < ii; i++) {
  var callback = pending[i];
  callback(value);
  }
  pending = undefined;
  },
  then: function (callback) {
  if (pending) {
  pending.push(callback);
  } else {
  callback(value);
  }
  }
  }
  };
  当调用then的时候,把所有的回调函数存在一个队列中,当调用resolve方法后,依次将队列中的回调函数取出来执行
  varref = function (value) {
  if (value && typeof value.then === "function")
  return value;
  return {
  then: function (callback) {
  return ref(callback(value));
  }
  };
  };
  这一段代码实现的级联的功能,采用了递归。如果传递的是一个promise那么就会直接返回这个promise,但是如果传递的是一个值,那么会将这个值包装成一个promise。
  下面promise 和ajax 结合例子:
  functionajax(url) {
  return new Promise(function(resolve, reject) {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
  if ((xhr.status >= 200 && xhr.status < 300) ||xhr.status == 304 ) {
  resovle(xhr.responseText);
  } else {
  reject( xhr.status);
  }
  }
  xhr.open("GET", url, false);
  xhr.send();
  });
  }
  ajax("/test.json")
  .then(function(data){
  console.log(data);
  })
  .cacth(function(err){
  console.log(err);
  });generator
  基本用法
  function* gen (x) {
  const y = yield x + 2;
  // console.log(y); // 猜猜会打印出什么值
  }
  constg = gen(1);
  console.log("first",g.next()); //first { value: 3, done: false }
  console.log("second",g.next()); // second { value: undefined, done: true }
  通俗的理解一下就是yield关键字会交出函数的执行权,next方法会交回执行权,yield会把generator中yield后面的执行结果,带到函数外面,而next方法会把外面的数据返回给generator中yield左边的变量。这样就实现了数据的双向流动。
  generator实现异步编程
  我们来看generator如何是如何来实现一个异步编程(*)
  constfs = require("fs");
  function* gen() {
  try {
  const file = yield fs.readFile;
  console.log(file.toString());
  } catch(e) {
  console.log("捕获到异常",e);
  }
  }
  //执行器
  constg = gen();
  g.next().value("./config1.json",function (error, value) {
  if(error) {
  g.throw("文件不存在");
  }
  g.next(value);
  });
  那么我们next中的参数就会是上一个yield函数的返回结果,可以看到在generator函数中的代码感觉是同步的,但是要想执行这个看似同步的代码,过程却很复杂,也就是流程管理很复杂。
  扩展:异步编程与多线程的区别
  共同点:
  异步和多线程两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性
  不同点:线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线 程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些出入,而且难以调试。
  这里有一个疑问。异步操作没有创建新的线程,我们一定会想,比如有一个文件操作,大量数据从硬盘上读取,若使用单线程的同步操作自然要等待会很长时间,但是若使用异步操作的话,我们让数据读取异步进行,二线程在数据读取期间去干其他的事情,我们会想,这怎么行呢,异步没有创建其他的线程,一个线程去干其他的事情去了,那数据的读取异步执行是去由谁完成的呢?实际上,本质是这样的。
  熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。DMA就是直接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。
  即CPU在数据的长时间读取过程中,只需要做两件事,第一发布指令,开始数据交换;第二,交换结束,得到指令,CPU再进行后续操作。而中间读取数据漫长的等待过程,CPU本身就不需要参与,顺序执行就是我不参与但是我要干等着,效率低下;异步执行就是,我不需要参与那我就去干其他事情去了,你做完了再通知我就可以了(回调)。
  但是你想一下,如果有一些异步操作必须要CPU的参与才能完成呢,即我开始的那个线程是走不开的,这该怎么办呢,在.NET中,有线程池去完成,线程池会高效率的开启一个新的线程去完成异步操作,在python中这是系统自己去安排的,无需人工干预,这就比自己创建很多的线程更加高效。
  总结:"多线程",第一、最大的问题在于线程本身的调度和运行需要很多时间,因此不建议自己创建太大量的线程;第二、共享资源的调度比较难,涉及到死锁,上锁等相关的概念。"异步",异步最大的问题在于"回调",这增加了软件设计上的难度。
  在实际设计时,我们可以将两者结合起来:当需要执行I/O操作时,使用异步操作比使用线程+同步I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、WebService、HttpRequest以及.netRemoting等跨进程的调用。异步特别适用于大多数IO密集型的应用程序。而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处理大量的并发操作时就不合适了。

今夜陪我一起相思夜,幽静,月,清寒。今夜,倚着一窗月色,我把思念注入笔尖,只为你,吟一曲恋歌。大千世界,芸芸众生,好多的幸福,都远在天边,不可触及,遇见你,我知道,幸福就在手边,所以,我小心翼翼的穷人的钱是死钱大多数的穷为什么他们赚的是死钱?他们每天上着996的工作,拿着微薄的收入,从未想过要打破穷人的固有思维,希望通过本文可以让你有所启发,有所了解。现在的穷人早已不是传统中那种一穷二白穷人欺负穷人当今中国,太平盛世,和谐社会,洋溢着一片详和气氛。然而总有几个穷人发出不和谐之声,或抢劫同胞,或打杀同门,令百姓切齿,令穷人疾首。于是有人高声呐喊穷人不欺负穷人。穷人帮穷人,行吗?最牛结婚证火了,夫妻俩名字简直绝配,网友调侃孩子该叫啥对每一个家长来说,给孩子取名字都是一项意义非凡的事情,因为一个人的名字不仅仅会影响到之后别人听到这个名字的第一印象,也是父母给孩子的第一份礼物,有许多家长为了能够给孩子起一个好听还我错过的女孩子之前我在一家厂里上班,有一天下班的时候下雨了,我正准备去换衣服回家。有一个很漂亮的女孩子跑过来。下面是我们的对话。女孩子你带伞了没有?当时我想的是,我说带伞了,她肯定要用我的伞。于关于感情的诗句1不乱于心,不困于情,不畏将来,不念过往,如此,安好。2没有人值得你流泪,值得你这么做的人不会让你哭泣。3走完同一条街,回到两个世界4人生若只如初见,何事秋风悲画扇,等闲变却故人心用金钱来衡量的亲情既迂腐又现实的要命Hi,大家好。我是翎露,带你走进今天的故事不知道大家和我有没有同样的烦恼。我的原生家庭曾让我自卑的要命,甚至很长一段时间走不出原生家庭的阴影。最近更新的电视剧正青春中林睿就是因为原那些让你感觉文字之美的句子1。蒹葭苍苍,白露为霜所谓伊人,在水一方。2山有木兮木有枝,心悦君兮君不知。3,玲珑骰子安红豆,入骨相思知不知。4晓看天色暮看云,行也思君,坐也思君。5且将新火试新茶,诗酒趁年华。生命需要厚道厚道的人尊重每一个人,更能用一颗博大的胸襟包容身边的人。与人交往中,厚道的人,有风度,有气量,不斤斤计较,懂得谦虚礼让。好的人缘不靠猜,不靠算,而靠修,厚道的人因为有情有义办事靠谱辽宁杀妻骗保案真相告诫女孩,选伴侣这五种男人,再爱也不能嫁近几日,央视今日说法栏目,连续播放了一起名叫环岛离心力的案件,本以为这是一件普通的交通事故,随着调查的深入调查才发现,这是一起预谋已久的骗保案,整个事件的背后让让毛骨悚然,比起泰国李承铉全职带娃6年,抑郁1年,戚薇老公哭诉后,我终于理解了妈妈随着披荆斩棘的哥哥热播,有一位隐匿很久的艺人浮出水面,并且迅速俘虏女人的心,他就是超级奶爸李承铉,在披荆斩棘的哥哥热播之前,李承铉被冠以奶爸吃软饭的标签,随着节目的热播,他凭借一首
曾演李现母亲,8夺影后桂冠却无戏可演,如今47岁仍然未婚文Chuanye如果你问我,什么是好演员?我会回答用心演戏,做好案头工作,没一个角色都给人不同的感受!如果,你让我举一个例子,我会毫不犹豫说出一个名字颜丙燕!1为戏而生颜丙燕是孔圣色香味美,营养健康就是它啦文Allen今天小编给大家带来一道美食(蛋白炒玉米)关注我,每天都有新花样!这道菜比较简单,制作时间也不长,色香味美十分不错,馋哭小孩不在话下。光看着就已经特别有食欲。玉米和蛋白都流朱浣碧崔槿汐,甄嬛身边最得宠的宫女,最忠心的死的最早文Chuanye甄嬛误穿了纯元皇后的衣服,封妃梦想破灭,不过这本来就不是她在意的她最在意的是皇上的爱,可是没想到皇上竟然只是把她当成纯元皇后的影子。那一刻,甄嬛心灰意冷。她爱了皇上跟海清陶虹咏梅等大腕合作,35岁的她演得真实可怕文Chuanye最近有一部卧虎藏龙的影视剧和大家见面了!这部剧中有很多影帝影后!35岁的她虽然戏份不多,但是气场不输,很多人说,她演的角色真实到可拍!这部剧就是小欢喜!小欢喜讲的是甄嬛从未爱过皇上,是皇上实现了她的少女梦毁了她的少女梦文Chuanye甄嬛从来都没有想过要进宫。但是却不得不进宫。她一直以来想要的就是愿得一心人,白头不相离,皇上肯定不会是这个人。所以,刚进宫的时候,她选择避宠。除夕夜,甄嬛在倚梅园第端妃敬妃沈眉庄,整个后宫就她们三个对甄嬛是真心的文Chuanye甄嬛原本就是宫里一个不争不抢的人物形象,但是在各方势力的挑逗下,甄嬛变了。今天,小编给大家盘点一下接近甄嬛的妃嫔们到底有几个是对甄嬛好的!淳贵人是第一个和甄嬛住在一皇后祺贵人和安陵容在一条船上,为何还要废了安陵容的嗓子文Chuanye皇后祺贵人虽然和安陵容是一条船上的人,但是她们之间的矛盾非常大。说好了要一起组建打胎大队,为什么皇后祺贵人突然变了卦,要害安陵容?1祺贵人厌恶安陵容得宠。祺贵人看不太后讨厌端妃祺嫔安陵容胜过皇后,谁看明白了文Chuanye在甄嬛传里面有一个情节皇上病了,太后给皇上安排侍疾大队。宫里面主位以上的妃嫔都叫了,唯独没叫端妃祺嫔安陵容。因为太后讨厌她们。那太后为什么讨厌她们呢?1端妃被太后当皇上灌醉沈眉庄后不负责,彻底寒心的她向温实初表白了文Chuanye皇上和沈眉庄之间最大的矛盾就是华妃党了。因为华妃党的陷害,沈眉庄受了好多罪。而当时的皇上不仅不给沈眉庄解释的机会,反而严重惩罚了沈眉庄。沈眉庄寒心透了。沈眉庄沉冤得贞嫔祺贵人康常在一个比一个蠢,给甄嬛崔槿汐泼尽脏水得罪皇上文Chuanye在甄嬛传中,总有一些自不量力的角色,觉得自己家世不错,年轻貌美,就处处刁难别人。贞嫔祺贵人康常在就是这样的人。崔槿汐苏培盛的事情东窗事发后,她们三个人给甄嬛崔槿汐泼庆余年最值得娶得6个女人,5个凭实力上榜,婉儿不是在电视剧庆余年中,有许许多多的女性角色,这部剧中最值得娶的6个女人,5个凭实力上榜,唯独林婉儿不是!你知道都是谁吗?1范若若有才有德范若若是庆国第一才女,有貌有德,整个京城的男子女