内射老阿姨1区2区3区4区_久久精品人人做人人爽电影蜜月_久久国产精品亚洲77777_99精品又大又爽又粗少妇毛片

JavaScript在nodejs環(huán)境下執(zhí)行機(jī)制和事件循環(huán)的示例-創(chuàng)新互聯(lián)

小編給大家分享一下JavaScript在nodejs環(huán)境下執(zhí)行機(jī)制和事件循環(huán)的示例,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!

創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司提供網(wǎng)站設(shè)計(jì)和自適應(yīng)建站服務(wù)。團(tuán)隊(duì)由有經(jīng)驗(yàn)的網(wǎng)頁設(shè)計(jì)師、程序員和市場專家組成,能夠提供從H5技術(shù),網(wǎng)站制作,廣告投放平臺(tái),模板建站到小程序設(shè)計(jì)等全方位服務(wù)。 以客戶為中心,致力于為客戶提供創(chuàng)新、高效的解決方案,幫助您打造成功的企業(yè)網(wǎng)站。

1、說明

nodejs是單線程執(zhí)行的,同時(shí)它又是基于事件驅(qū)動(dòng)的非阻塞IO編程模型。這就使得我們不用等待異步操作結(jié)果返回,就可以繼續(xù)往下執(zhí)行代碼。當(dāng)異步事件觸發(fā)之后,就會(huì)通知主線程,主線程執(zhí)行相應(yīng)事件的回調(diào)。

本篇文章講解node中JavaScript的代碼的執(zhí)行流程,下面是測試代碼,如果你知道輸出的結(jié)果,那么就不需要再看本篇文章,如果不知道輸出結(jié)果,那么本片文章可幫助你了解:

console.log(1)
setTimeout(function () {
  new Promise(function (resolve) {
    console.log(2)
    resolve()
  })
  .then(() => { console.log(3) })
})
setTimeout(function () {
  console.log(4)
})

復(fù)雜的:

setTimeout(() => {
  console.log('1')
  new Promise((resolve) => { console.log('2'); resolve(); })
  .then(() => { console.log('3') })
  new Promise((resolve)=> { console.log('4'); resolve()})
  .then(() => { console.log('5') })
  setTimeout(() => { 
    console.log('6')
    setTimeout(() => {
      console.log('7')
      new Promise((resolve) => { console.log('8'); resolve() })
      .then( () => {  console.log('9') })
      new Promise((resolve) => { console.log('10'); resolve() })
      .then(() => {  console.log('11') })
    })
    setTimeout(() => { console.log('12') }, 0)
  })
  setTimeout(() => { console.log('13') }, 0)
})
setTimeout(() => { console.log('14') }, 0)
new Promise((resolve) => { console.log('15'); resolve() })
.then( ()=> { console.log('16') })
new Promise((resolve) => { console.log('17'); resolve() })
.then(() => { console.log('18') })

2. nodejs的啟動(dòng)過程

node.js啟動(dòng)過程可以分為以下步驟:

  1. 調(diào)用platformInit方法 ,初始化 nodejs 的運(yùn)行環(huán)境。
  2. 調(diào)用 performance_node_start 方法,對(duì) nodejs 進(jìn)行性能統(tǒng)計(jì)。
  3. openssl設(shè)置的判斷。
  4. 調(diào)用v8_platform.Initialize,初始化 libuv 線程池。
  5. 調(diào)用 V8::Initialize,初始化 V8 環(huán)境。
  6. 創(chuàng)建一個(gè)nodejs運(yùn)行實(shí)例。
  7. 啟動(dòng)上一步創(chuàng)建好的實(shí)例。
  8. 開始執(zhí)行js文件,同步代碼執(zhí)行完畢后,進(jìn)入事件循環(huán)。
  9. 在沒有任何可監(jiān)聽的事件時(shí),銷毀 nodejs 實(shí)例,程序執(zhí)行完畢。

JavaScript在nodejs環(huán)境下執(zhí)行機(jī)制和事件循環(huán)的示例

3. nodejs的事件循環(huán)詳解

Nodejs 將消息循環(huán)又細(xì)分為 6 個(gè)階段(官方叫做 Phase), 每個(gè)階段都會(huì)有一個(gè)類似于隊(duì)列的結(jié)構(gòu), 存儲(chǔ)著該階段需要處理的回調(diào)函數(shù).

Nodejs 為了防止某個(gè) 階段 任務(wù)太多, 導(dǎo)致后續(xù)的 階段 發(fā)生饑餓的現(xiàn)象, 所以消息循環(huán)的每一個(gè)迭代(iterate) 中, 每個(gè) 階段 執(zhí)行回調(diào)都有個(gè)大數(shù)量. 如果超過數(shù)量的話也會(huì)強(qiáng)行結(jié)束當(dāng)前 階段而進(jìn)入下一個(gè) 階段. 這一條規(guī)則適用于消息循環(huán)中的每一個(gè) 階段.

3.1 Timer 階段

這是消息循環(huán)的第一個(gè)階段, 用一個(gè) for 循環(huán)處理所有 setTimeoutsetInterval 的回調(diào).

這些回調(diào)被保存在一個(gè)最小堆(min heap) 中. 這樣引擎只需要每次判斷頭元素, 如果符合條件就拿出來執(zhí)行, 直到遇到一個(gè)不符合條件或者隊(duì)列空了, 才結(jié)束 Timer Phase.

Timer 階段中判斷某個(gè)回調(diào)是否符合條件的方法也很簡單. 消息循環(huán)每次進(jìn)入 Timer 的時(shí)候都會(huì)保存一下當(dāng)時(shí)的系統(tǒng)時(shí)間,然后只要看上述最小堆中的回調(diào)函數(shù)設(shè)置的啟動(dòng)時(shí)間是否超過進(jìn)入 Timer 時(shí)保存的時(shí)間, 如果超過就拿出來執(zhí)行.

3.2 Pending I/O Callback 階段

執(zhí)行除了close callbacks、setTimeout()、setInterval()、setImmediate()回調(diào)之外幾乎所有回調(diào),比如說TCP連接發(fā)生錯(cuò)誤、 fs.read, socket 等 IO 操作的回調(diào)函數(shù), 同時(shí)也包括各種 error 的回調(diào).

3.3 Idle, Prepare 階段

系統(tǒng)內(nèi)部的一些調(diào)用。

3.4 Poll 階段,重要階段

這是整個(gè)消息循環(huán)中最重要的一個(gè) 階段, 作用是等待異步請求和數(shù)據(jù),因?yàn)樗瘟苏麄€(gè)消息循環(huán)機(jī)制.

poll階段有兩個(gè)主要的功能:一是執(zhí)行下限時(shí)間已經(jīng)達(dá)到的timers的回調(diào),一是處理poll隊(duì)列里的事件。
注:Node的很多API都是基于事件訂閱完成的,比如fs.readFile,這些回調(diào)應(yīng)該都在poll階段完成。

當(dāng)事件循環(huán)進(jìn)入poll階段:

  • poll隊(duì)列不為空的時(shí)候,事件循環(huán)肯定是先遍歷隊(duì)列并同步執(zhí)行回調(diào),直到隊(duì)列清空或執(zhí)行回調(diào)數(shù)達(dá)到系統(tǒng)上限。
  • poll隊(duì)列為空的時(shí)候,這里有兩種情況。

    • 如果代碼已經(jīng)被setImmediate()設(shè)定了回調(diào),那么事件循環(huán)直接結(jié)束poll階段進(jìn)入check階段來執(zhí)行check隊(duì)列里的回調(diào)。
    • 如果代碼沒有被設(shè)定setImmediate()設(shè)定回調(diào):

      • 如果有被設(shè)定的timers,那么此時(shí)事件循環(huán)會(huì)檢查timers,如果有一個(gè)或多個(gè)timers下限時(shí)間已經(jīng)到達(dá),那么事件循環(huán)將繞回timers階段,并執(zhí)行timers的有效回調(diào)隊(duì)列。
      • 如果沒有被設(shè)定timers,這個(gè)時(shí)候事件循環(huán)是阻塞在poll階段等待事件回調(diào)被加入poll隊(duì)列。

Poll階段,當(dāng)js層代碼注冊的事件回調(diào)都沒有返回的時(shí)候,事件循環(huán)會(huì)暫時(shí)阻塞在poll階段,解除阻塞的條件:

  1. 在poll階段執(zhí)行的時(shí)候,會(huì)傳入一個(gè)timeout超時(shí)時(shí)間,該超時(shí)時(shí)間就是poll階段的大阻塞時(shí)間。
  2. timeout時(shí)間未到的時(shí)候,如果有事件返回,就執(zhí)行該事件注冊的回調(diào)函數(shù)。timeout超時(shí)時(shí)間到了,則退出poll階段,執(zhí)行下一個(gè)階段。

這個(gè) timeout 設(shè)置為多少合適呢? 答案就是 Timer Phase 中最近要執(zhí)行的回調(diào)啟動(dòng)時(shí)間到現(xiàn)在的差值, 假設(shè)這個(gè)差值是 detal. 因?yàn)?Poll Phase 后面沒有等待執(zhí)行的回調(diào)了. 所以這里最多等待 delta 時(shí)長, 如果期間有事件喚醒了消息循環(huán), 那么就繼續(xù)下一個(gè) Phase 的工作; 如果期間什么都沒發(fā)生, 那么到了 timeout 后, 消息循環(huán)依然要進(jìn)入后面的 Phase, 讓下一個(gè)迭代的 Timer Phase 也能夠得到執(zhí)行.
Nodejs 就是通過 Poll Phase, 對(duì) IO 事件的等待和內(nèi)核異步事件的到達(dá)來驅(qū)動(dòng)整個(gè)消息循環(huán)的.

3.5 Check  階段

這個(gè)階段只處理 setImmediate 的回調(diào)函數(shù).
那么為什么這里要有專門一個(gè)處理 setImmediate 的 階段 呢? 簡單來說, 是因?yàn)?Poll 階段可能設(shè)置一些回調(diào), 希望在 Poll 階段 后運(yùn)行. 所以在 Poll 階段 后面增加了這個(gè) Check 階段.

3.6 Close Callbacks 階段

專門處理一些 close 類型的回調(diào). 比如 socket.on('close', ...). 用于資源清理.

4. nodejs執(zhí)行JS代碼過程及事件循環(huán)過程

1、node初始化

初始化node環(huán)境

執(zhí)行輸入的代碼

執(zhí)行process.nextTick回調(diào)

執(zhí)行微任務(wù)(microtasks)

2、進(jìn)入事件循環(huán)

2.1、進(jìn)入Timer階段

  • 檢查Timer隊(duì)列是否有到期的Timer的回調(diào),如果有,將到期的所有Timer回調(diào)按照TimerId升序執(zhí)行
  • 檢查是否有process.nextTick任務(wù),如果有,全部執(zhí)行
  • 檢查是否有微任務(wù)(promise),如果有,全部執(zhí)行
  • 退出該階段

2.2、進(jìn)入Pending I/O Callback階段

  • 檢查是否有Pending I/O Callback的回調(diào),如果有,執(zhí)行回調(diào)。如果沒有退出該階段
  • 檢查是否有process.nextTick任務(wù),如果有,全部執(zhí)行
  • 檢查是否有微任務(wù)(promise),如果有,全部執(zhí)行
  • 退出該階段

2.3、進(jìn)入idle,prepare階段

這個(gè)階段與JavaScript關(guān)系不大,略過

2.4、進(jìn)入Poll階段

首先檢查是否存在尚未完成的回調(diào),如果存在,分如下兩種情況:

第一種情況:有可執(zhí)行的回調(diào)

執(zhí)行所有可用回調(diào)(包含到期的定時(shí)器還有一些IO事件等)

檢查是否有process.nextTick任務(wù),如果有,全部執(zhí)行

檢查是否有微任務(wù)(promise),如果有,全部執(zhí)行


退出該階段

第二種情況:沒有可執(zhí)行的回調(diào)

檢查是否有immediate回調(diào),如果有,退出Poll階段。如果沒有,阻塞在此階段,等待新的事件通知


如果不存在尚未完成的回調(diào),退出Poll階段


2.5、進(jìn)入check階段

如果有immediate回調(diào),則執(zhí)行所有immediate回調(diào)

檢查是否有process.nextTick任務(wù),如果有,全部執(zhí)行


檢查是否有微任務(wù)(promise),如果有,全部執(zhí)行

退出該階段

2.6、進(jìn)入closing階段

如果有immediate回調(diào),則執(zhí)行所有immediate回調(diào)

檢查是否有process.nextTick任務(wù),如果有,全部執(zhí)行

檢查是否有微任務(wù)(promise),如果有,全部執(zhí)行

退出該階段

3、檢查是否有活躍的handles(定時(shí)器、IO等事件句柄)

如果有,繼續(xù)下一輪事件循環(huán)


如果沒有,結(jié)束事件循環(huán),退出程序

注意:

事件循環(huán)的每一個(gè)子階段退出之前都會(huì)按順序執(zhí)行如下過程:

檢查是否有 process.nextTick 回調(diào),如果有,全部執(zhí)行。


檢查是否有 微任務(wù)(promise),如果有,全部執(zhí)行。

4.1 關(guān)于Promise和process.nextTick

事件循環(huán)隊(duì)列先保證所有的process.nextTick回調(diào),然后將所有的Promise回調(diào)追加在后面,最終在每個(gè)階段結(jié)束的時(shí)候一次性拿出來執(zhí)行。

此外,process.nextTickPromise回調(diào)的數(shù)量是受限制的,也就是說,如果一直往這個(gè)隊(duì)列中加入回調(diào),那么整個(gè)事件循環(huán)就會(huì)被卡住。

JavaScript在nodejs環(huán)境下執(zhí)行機(jī)制和事件循環(huán)的示例

4.2 關(guān)于setTimeout(…, 0) 和 setImmediate

這兩個(gè)方法的回調(diào)到底誰快?

如下面的例子:

setImmediate(() => console.log(2))
setTimeout(() => console.log(1))

使用nodejs多次執(zhí)行后,發(fā)現(xiàn)輸出結(jié)果有時(shí)是1 2,有時(shí)是2 1

對(duì)于多次執(zhí)行輸出結(jié)果不同,需要了解事件循環(huán)的基礎(chǔ)問題。

首先,Nodejs啟動(dòng),初始化環(huán)境后加載我們的JS代碼(index.js).發(fā)生了兩件事(此時(shí)尚未進(jìn)入消息循環(huán)環(huán)節(jié)):

setImmediate 向 Check 階段 中添加了回調(diào) console.log(2);

setTimeout 向 Timer 階段 中添加了回調(diào) console.log(1)

這時(shí)候, 要初始化階段完畢, 要進(jìn)入 Nodejs 消息循環(huán)了。

為什么會(huì)有兩種輸出呢? 接下來一步很關(guān)鍵:

當(dāng)執(zhí)行到 Timer 階段 時(shí), 會(huì)發(fā)生兩種可能. 因?yàn)槊恳惠喌鷦倓傔M(jìn)入 Timer 階段 時(shí)會(huì)取系統(tǒng)時(shí)間保存起來, 以 ms(毫秒) 為最小單位.

如果 Timer 階段 中回調(diào)預(yù)設(shè)的時(shí)間 > 消息循環(huán)所保存的時(shí)間, 則執(zhí)行 Timer 階段 中的該回調(diào). 這種情況下先輸出 1, 直到 Check 階段 執(zhí)行后,輸出2.總的來說, 結(jié)果是 1 2.

如果運(yùn)行比較快, Timer 階段 中回調(diào)預(yù)設(shè)的時(shí)間可能剛好等于消息循環(huán)所保存的時(shí)間, 這種情況下, Timer 階段 中的回調(diào)得不到執(zhí)行, 則繼續(xù)下一個(gè) 階段. 直到 Check 階段, 輸出 2. 然后等下一輪迭代的 Timer 階段, 這時(shí)的時(shí)間一定是滿足 Timer 階段 中回調(diào)預(yù)設(shè)的時(shí)間 > 消息循環(huán)所保存的時(shí)間 , 所以 console.log(1) 得到執(zhí)行, 輸出 1. 總的來說, 結(jié)果就是 2 1.

所以, 輸出不穩(wěn)定的原因就取決于進(jìn)入 Timer 階段 的時(shí)間是否和執(zhí)行 setTimeout 的時(shí)間在 1ms 內(nèi). 如果把代碼改成如下, 則一定會(huì)得到穩(wěn)定的輸出:

require('fs').readFile('my-file-path.txt', () => {
 setImmediate(() => console.log(2))
 setTimeout(() => console.log(1))
});

這是因?yàn)橄⒀h(huán)在 Pneding I/O Phase 才向 Timer 和 Check 隊(duì)列插入回調(diào). 這時(shí)按照消息循環(huán)的執(zhí)行順序, Check 一定在 Timer 之前執(zhí)行。

從性能角度講, setTimeout 的處理是在 Timer Phase, 其中 min heap 保存了 timer 的回調(diào), 因此每執(zhí)行一個(gè)回調(diào)的同時(shí)都會(huì)涉及到堆調(diào)整. 而 setImmediate 僅僅是清空一個(gè)隊(duì)列. 效率自然會(huì)高很多.

再從執(zhí)行時(shí)機(jī)上講. setTimeout(..., 0) 和 setImmediate 完全屬于兩個(gè)階段.

5. 一個(gè)實(shí)際例子演示

下面以一段代碼來說明nodejs運(yùn)行JavaScript的機(jī)制。

如下面一段代碼:

setTimeout(() => {                                                // settimeout1
  console.log('1')
  new Promise((resolve) => { console.log('2'); resolve(); })      // Promise3
  .then(() => { console.log('3') })
  new Promise((resolve)=> { console.log('4'); resolve()})         // Promise4
  .then(() => { console.log('5') })
  setTimeout(() => {                                              // settimeout3
    console.log('6')
    setTimeout(() => {                                            // settimeout5
      console.log('7')
      new Promise((resolve) => { console.log('8'); resolve() })   // Promise5
      .then( () => {  console.log('9') })
      new Promise((resolve) => { console.log('10'); resolve() })  // Promise6
      .then(() => {  console.log('11') })
    })
    setTimeout(() => { console.log('12') }, 0)                    // settimeout6
  })
  setTimeout(() => { console.log('13') }, 0)                      // settimeout4
})
setTimeout(() => { console.log('14') }, 0)                        // settimeout2
new Promise((resolve) => { console.log('15'); resolve() })        // Promise1
.then( ()=> { console.log('16') })
new Promise((resolve) => { console.log('17'); resolve() })        // Promise2
.then(() => { console.log('18') })

上面代碼執(zhí)行過程:

node初始化

執(zhí)行JavaScript代碼

遇到setTimeout, 把回調(diào)函數(shù)放到Timer隊(duì)列中,記為settimeout1


遇到setTimeout, 把回調(diào)函數(shù)放到Timer隊(duì)列中,記為settimeout2


遇到Promise,執(zhí)行,輸出15,把回調(diào)函數(shù)放到微任務(wù)隊(duì)列,記為Promise1


遇到Promise,執(zhí)行,輸出17,把回調(diào)函數(shù)放到微任務(wù)隊(duì)列,記為Promise2


代碼執(zhí)行結(jié)束,此階段輸出結(jié)果:15 17


沒有process.nextTick回調(diào),略過


執(zhí)行微任務(wù)

檢查微任務(wù)隊(duì)列是否有可執(zhí)行回調(diào),此時(shí)隊(duì)列有2個(gè)回調(diào):Promise1、Promise2

執(zhí)行Promise1回調(diào),輸出16


執(zhí)行Promise2回調(diào),輸出18


此階段輸出結(jié)果:16 18


進(jìn)入第一次事件循環(huán)

進(jìn)入Timer階段

檢查Timer隊(duì)列是否有可執(zhí)行的回調(diào),此時(shí)隊(duì)列有2個(gè)回調(diào):settimeout1、settimeout2


執(zhí)行settimeout1回調(diào):

輸出1、2、4


添加了2個(gè)微任務(wù),記為Promise3、Promise4


添加了2個(gè)Timer任務(wù),記為settimeout3、settimeout4


執(zhí)行settimeout2回調(diào),輸出14


Timer隊(duì)列任務(wù)執(zhí)行完畢


沒有process.nextTick回調(diào),略過


檢查微任務(wù)隊(duì)列是否有可執(zhí)行回調(diào),此時(shí)隊(duì)列有2個(gè)回調(diào):Promise3、Promise4


按順序執(zhí)行2個(gè)微任務(wù),輸出3、5


此階段輸出結(jié)果:1 2 4 14 3 5

Pending I/O Callback階段沒有任務(wù),略過


進(jìn)入 Poll 階段

檢查是否存在尚未完成的回調(diào),此時(shí)有2個(gè)回調(diào):settimeout3、settimeout4

執(zhí)行settimeout3回調(diào)

輸出6

添加了2個(gè)Timer任務(wù),記為settimeout5、settimeout6

執(zhí)行settimeout4回調(diào),輸出13

沒有process.nextTick回調(diào),略過


沒有微任務(wù),略過


此階段輸出結(jié)果:6 13


check、closing階段沒有任務(wù),略過


檢查是否還有活躍的handles(定時(shí)器、IO等事件句柄),有,繼續(xù)下一輪事件循環(huán)


進(jìn)入第二次事件循環(huán)

進(jìn)入Timer階段

檢查Timer隊(duì)列是否有可執(zhí)行的回調(diào),此時(shí)隊(duì)列有2個(gè)回調(diào):settimeout5、settimeout6


執(zhí)行settimeout5回調(diào):

輸出7、 8、10


添加了2個(gè)微任務(wù),記為Promise5、Promise6


執(zhí)行settimeout6回調(diào),輸出12


沒有process.nextTick回調(diào),略過


檢查微任務(wù)隊(duì)列是否有可執(zhí)行回調(diào),此時(shí)隊(duì)列有2個(gè)回調(diào):Promise5、Promise6


按順序執(zhí)行2個(gè)微任務(wù),輸出9、11


此階段輸出結(jié)果:7 8 10 12 9 11


Pending I/O Callback、Poll、check、closing階段沒有任務(wù),略過


檢查是否還有活躍的handles(定時(shí)器、IO等事件句柄),沒有了,結(jié)束事件循環(huán),退出程序


程序執(zhí)行結(jié)束,輸出結(jié)果:15 17 16 18 1 2 4 14 3 5 6 13 7 8 10 12 9 11


JavaScript在nodejs環(huán)境下執(zhí)行機(jī)制和事件循環(huán)的示例

看完了這篇文章,相信你對(duì)JavaScript在nodejs環(huán)境下執(zhí)行機(jī)制和事件循環(huán)的示例有了一定的了解,想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

當(dāng)前文章:JavaScript在nodejs環(huán)境下執(zhí)行機(jī)制和事件循環(huán)的示例-創(chuàng)新互聯(lián)
鏈接分享:http://www.rwnh.cn/article44/epghe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、關(guān)鍵詞優(yōu)化網(wǎng)站內(nèi)鏈、App開發(fā)軟件開發(fā)、自適應(yīng)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化
海城市| 满洲里市| 岳池县| 陇西县| 嘉荫县| 天门市| 兴海县| 阜新| 山阳县| 湾仔区| 岳阳县| 文成县| 满洲里市| 周宁县| 拜泉县| 宜昌市| 凭祥市| 建德市| 麻栗坡县| 湖北省| 万载县| 蛟河市| 陆良县| 渝中区| 龙海市| 元阳县| 思茅市| 齐河县| 广宁县| 海城市| 张家界市| 驻马店市| 烟台市| 宣城市| 靖远县| 赤壁市| 浪卡子县| 绥滨县| 综艺| 孟州市| 虎林市|