中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

做網(wǎng)站每頁面費(fèi)用/bing搜索引擎國(guó)際版

做網(wǎng)站每頁面費(fèi)用,bing搜索引擎國(guó)際版,網(wǎng)站建設(shè) 九艾,東莞兼職招聘網(wǎng)最新招聘有限狀態(tài)機(jī)是一種數(shù)學(xué)計(jì)算模型,它描述了在任何給定時(shí)間只能處于一種狀態(tài)的系統(tǒng)的行為。形式上,有限狀態(tài)機(jī)有五個(gè)部分: 初始狀態(tài)值 (initial state)有限的一組狀態(tài) (states)有限的一組事件 (events)由事件驅(qū)動(dòng)的一組狀態(tài)轉(zhuǎn)移關(guān)系 (transition…

有限狀態(tài)機(jī)是一種數(shù)學(xué)計(jì)算模型,它描述了在任何給定時(shí)間只能處于一種狀態(tài)的系統(tǒng)的行為。形式上,有限狀態(tài)機(jī)有五個(gè)部分:

  • 初始狀態(tài)值 (initial state)
  • 有限的一組狀態(tài) (states)
  • 有限的一組事件 (events)
  • 由事件驅(qū)動(dòng)的一組狀態(tài)轉(zhuǎn)移關(guān)系 (transitions)
  • 有限的一組最終狀態(tài) (final states)

狀態(tài)是指由狀態(tài)機(jī)建模的系統(tǒng)中某種有限的、定性的“模式”或“狀態(tài)”,并不描述與該系統(tǒng)相關(guān)的所有(可能是無限的)數(shù)據(jù)。例如,水可以處于以下 4 種狀態(tài)中的一種:冰、液體、氣體或等離子體。然而,水的溫度可以變化,所以其測(cè)量值是定量的和無限的。再比如管理TCP Socket連接時(shí),其生命周期內(nèi)存在明顯的有限狀態(tài)轉(zhuǎn)換。

可能有相當(dāng)多的同學(xué)在開發(fā)中沒意識(shí)到有限狀態(tài)機(jī)的作用,但是實(shí)際上,我們幾乎無時(shí)不刻在有意無意間使用了有限狀態(tài)機(jī)。當(dāng)您在開發(fā)過程中能有意識(shí)地系統(tǒng)地進(jìn)行有限狀態(tài)分析并應(yīng)用有限狀態(tài)機(jī),往往代表著您達(dá)到了較高的水平。

目前開源的有限狀態(tài)機(jī)實(shí)現(xiàn)中比較知名的有:

  • xstate:堪稱狀態(tài)機(jī)航空母艦,功能太強(qiáng)大了,也太復(fù)雜了,學(xué)習(xí)成本非常高。
  • Javascript State Machine:功能較弱,在實(shí)際試用過程中發(fā)現(xiàn)在進(jìn)行異步切換時(shí)存在問題。
  • jssm:特點(diǎn)是引入自己的DSL語法來描述狀態(tài)機(jī),使用起來比較別扭。

事實(shí)上,從功能完整度上看xstate是第一選擇,但是其過于復(fù)雜了,在功能與易用平衡方面并不理想。

因此,我們開發(fā)了FlexState有限狀態(tài)機(jī),力求在功能性、易用性上達(dá)到平衡

FlexState是一款簡(jiǎn)單易用的有限狀態(tài)機(jī),具有以下特性:

  1. 支持基于Class構(gòu)建有限狀態(tài)機(jī)實(shí)例
  2. 支持狀態(tài)enter/leave/resume/done鉤子事件
  3. 狀態(tài)切換完全支持異步操作
  4. 支持定義異步狀態(tài)動(dòng)作Action
  5. 支持狀態(tài)切換生命周期事件訂閱
  6. 支持錯(cuò)誤處理和狀態(tài)切換中止
  7. 基于TypeScript開發(fā)
  8. 支持子狀態(tài)
  9. 核心代碼90%+單元測(cè)試覆蓋率

Github
官網(wǎng)

快速入門

下面我們以開發(fā)基于nodejs/net.socket的TCP客戶端為例來說明FlexStateMachine的使用。

作為例子,我們?yōu)?code>TCPClient設(shè)計(jì)以下幾種狀態(tài):

  • Initial:初始狀態(tài),構(gòu)建socket實(shí)例后處于該階段。
  • Connecting:連接中,當(dāng)調(diào)用Connect方法,觸發(fā)connect事件前。
  • Connected:已連接,當(dāng)觸發(fā)connect事件后。
  • Disconnecting:正在斷開,當(dāng)調(diào)用destory或end方法后,end/close事件觸發(fā)前。
  • Disconnected:被動(dòng)斷開,當(dāng)觸發(fā)end/close事件后。
  • AlwaysDisconnected: 主動(dòng)斷開狀態(tài)
  • IDLE: 自動(dòng)添加的空閑狀態(tài),狀態(tài)機(jī)未啟動(dòng)時(shí)
  • ERROR: 自動(dòng)添加的錯(cuò)誤狀態(tài),特殊的FINAL狀態(tài)

TCPClient的狀態(tài)圖如下:

第一步:構(gòu)建狀態(tài)機(jī)

推薦直接繼承FlexStateMachine來創(chuàng)建一個(gè)TCPClient實(shí)例,該種方式更加簡(jiǎn)單易用。


import { state, FlexStateMachine } from "flexstate"class TcpClient extends FlexStateMachine{// 定義狀態(tài)static states = { Initial : { value:0, title:"已初始化", next:["Connecting","Connected","Disconnected"],initial:true},Connecting	: { value:1, title:"正在連接...", next:["Connected","Disconnected"] },Connected : { value:2, title:"已連接", next:["Disconnecting","Disconnected"] },Disconnecting : { value:3, title:"正在斷開連接...", next:["Disconnected"] },Disconnected : {value:4, title:"已斷開連接", next:["Connecting"]},AlwaysDisconnected	: {value:5, title:"已主動(dòng)斷開連接", next:["Connecting"]}}                   constructor(options:FlexStateOptions){super(Object.assign({host:"",port:9000,autoStart:true,context           : null,                // 狀態(tài)上下文對(duì)象,當(dāng)執(zhí)行動(dòng)作或狀態(tài)轉(zhuǎn)換事件時(shí)的this指向autoStart         : true,                // 自動(dòng)啟動(dòng)狀態(tài)機(jī)timeout           : 30 * 1000            // 當(dāng)執(zhí)行狀態(tài)切換回調(diào)時(shí)的超時(shí),如enter、leave、done回調(diào)injectActionMethod: true,                // 將動(dòng)作方法注入到當(dāng)前實(shí)例中  },options)) } @state{when:["Initial","Disconnected","Error"],   // 代表只能當(dāng)處于此三種狀態(tài)時(shí)才允許調(diào)用連接方法    pending:"Connecting",						// 執(zhí)行后進(jìn)入正在連接中的狀態(tài)}connect(){this._socket.connect(this.options)    } @state({when:["Connected"],     	// 代表只有在已連接狀態(tài)才允許執(zhí)行斷開方法pending:"Disconnecting"})  disconnect(){this._socket.destory()}// 當(dāng)狀態(tài)轉(zhuǎn)換成功后會(huì)調(diào)用此方法ontTransition({error,from,to,done,timeConsuming}){console.log(`從<${previous}>轉(zhuǎn)換到<current>,耗時(shí):${timeConsuming}ms`)       // 例 ==> 從<Connecting>轉(zhuǎn)換到<Connected,耗時(shí)12ms>console.log(this.current)                          // {name,value,....}}onData(data){....}}

說明:

  • 以上我們創(chuàng)建了一個(gè)繼承自FlexStateMachine來創(chuàng)建一個(gè)TCPClient實(shí)例
  • 并且定義了Initial、ConnectingConnected、Disconnecting、Disconnected、AlwaysDisconnected共六個(gè)狀態(tài)以及狀態(tài)之間的轉(zhuǎn)換約束。同時(shí),狀態(tài)機(jī)還會(huì)自動(dòng)添加一個(gè)ERRORIDLE狀態(tài)。
  • 定義了connectdisconnect兩個(gè)動(dòng)作action,在這兩個(gè)方法前添加@state代表了當(dāng)執(zhí)行這兩個(gè)方法會(huì)導(dǎo)致狀態(tài)變化。

第二步:初始化TCPSocket

當(dāng)實(shí)例化TCPClient實(shí)例后,首先應(yīng)該創(chuàng)建Socket實(shí)例。由于TCPClient實(shí)例繼承自FlexStateMachine,并且我們指定了Initial為初始化狀態(tài)。
狀態(tài)機(jī)會(huì)在實(shí)例化并啟動(dòng)后自動(dòng)轉(zhuǎn)換到Initial狀態(tài)。因此,我們可以在進(jìn)入Initial狀態(tài)前進(jìn)行初始化操作。

class TcpClient extends FlexStateMachine{// 轉(zhuǎn)換至Initial狀態(tài)前會(huì)調(diào)用方法async onInitialEnter({retry,retryCount}){try{      this._socket = new net.Socket()// 當(dāng)連接成功時(shí),切換到Connected事件; 每一個(gè)狀態(tài)均有一個(gè)大寫的狀態(tài)值實(shí)例成員// this.CONNECTED==this.states.Connected.valuethis._socket.on("connect",()=>this.transition(this.CONNECTED)) this._socket.on("close",()=>{//....     詳見后續(xù)重連說明}) 		// 套接字因不活動(dòng)而超時(shí)則觸發(fā),這只是通知套接字已空閑,用戶必須手動(dòng)關(guān)閉連接。// 通過事件觸發(fā)方式來執(zhí)行disconnect動(dòng)作this._socket.on("timeout",()=>this.emit("disconnect"))this._socket.on("error",()=>this.transition(this.ERROR))this._socket.on("data",this.onData.bind(this))}catch(e){if(retryCount<3){retry(1000)                                      // 1000ms后重試執(zhí)行}else{				//throw e}      }
}

當(dāng)TCPClient實(shí)例化,狀態(tài)機(jī)處于IDLE狀態(tài)(<tcp實(shí)例>.current.name=='IDLE'),然后狀態(tài)機(jī)自動(dòng)啟動(dòng)(autoStart=true)將轉(zhuǎn)換至Initial狀態(tài)(initial狀態(tài))。

  • 狀態(tài)機(jī)轉(zhuǎn)換至Initial狀態(tài)前會(huì)調(diào)用onInitialEnter。我們可以在此方法中創(chuàng)建TCP Socket實(shí)例以及其他相關(guān)的初始化。
  • onInitialEnter成功執(zhí)行完畢后,狀態(tài)機(jī)的狀態(tài)將轉(zhuǎn)換至Initial。(IDLE->Initial
  • 如果在onInitialEnter函數(shù)初始化失敗或出錯(cuò),則應(yīng)該拋出錯(cuò)誤。錯(cuò)誤將導(dǎo)致狀態(tài)機(jī)將無法轉(zhuǎn)換至Initial狀態(tài),也就無法進(jìn)行后續(xù)的所有操作了。一般在初始化失敗時(shí),會(huì)進(jìn)行如下操作:
    • 進(jìn)行重試操作,直至初始化成功(即成功創(chuàng)建好Socket并進(jìn)行相應(yīng)的事件綁定)。
    • 反復(fù)重試多次失敗后,也可能會(huì)放棄重試,TCP Client將無法切換到Initial狀態(tài),而是保持在IDLE狀態(tài)。
    • 當(dāng)條件具備時(shí),狀態(tài)機(jī)需要重新運(yùn)行(即調(diào)用tcp.start()來啟動(dòng)狀態(tài)機(jī)),將重復(fù)上述過程。

第三步:連接服務(wù)器

當(dāng)TCPClient實(shí)例初始化完成后,就可以開始連接服務(wù)器。我們可以在類上創(chuàng)建狀態(tài)機(jī)動(dòng)作connect,啟動(dòng)連接操作。

import { state, FlexStateMachine } from "flexstate"class TcpClient extends FlexStateMachine{// 通過裝飾器來聲明這是一個(gè)狀態(tài)動(dòng)作  @state({// 代表只能當(dāng)處于此三種狀態(tài)時(shí)才允許執(zhí)行動(dòng)作,即調(diào)用連接方法when:["Initial","Disconnected","Error"],      // 執(zhí)行后進(jìn)入正在連接中的狀態(tài)pending:"Connecting"	})                async connect(){      this._socket.connect(this.options)          }
}
// 創(chuàng)建連接實(shí)例
let tcp = new TcpClient({...})
// 連接
tcp.connect()   
// 狀態(tài)機(jī)狀態(tài)將變化: Initial -> Connecting -> Connected
// 如果連接出錯(cuò)狀態(tài)將變化:Initial -> Connecting -> Error

上述的@state({....})定義了一個(gè)狀態(tài)機(jī)動(dòng)作,代表當(dāng)調(diào)用connect方法時(shí)會(huì)導(dǎo)致一系列的狀態(tài)轉(zhuǎn)換:

  • 動(dòng)作名稱為connect,會(huì)創(chuàng)建一個(gè)同名的實(shí)例方法tcp.connect替換掉原始的connect方法。
  • when參數(shù)代表了只有當(dāng)前狀態(tài)為[Initial、Disconnected、Error]其中一個(gè)時(shí)才允許執(zhí)行connect動(dòng)作。
  • pending="Connecting"代表,執(zhí)行connect動(dòng)作前,狀態(tài)機(jī)的狀態(tài)將暫時(shí)會(huì)切換至Connecting,也就是會(huì)顯示正在連接中。由于連接操作可能是耗時(shí)的,所有設(shè)計(jì)一個(gè)正在連接中是比較符合實(shí)際業(yè)務(wù)邏輯的。
  • 如果執(zhí)行socket.connect({...}) 出錯(cuò),可以通過@state({retry,retryCount})來啟用重試邏輯。需要注意的是 調(diào)用connect成功僅僅代表該方法在調(diào)用時(shí)沒有出錯(cuò),并不代表已經(jīng)連接成功。是否連接成功需要由socket/connect事件來觸發(fā)確認(rèn)。
  • 在上述中,并沒有顯式指定當(dāng)連接成功時(shí)的狀態(tài),原因是因?yàn)?code>connect方法是一個(gè)異步方法,是否連接成功或失敗是通過事件回調(diào)的方式轉(zhuǎn)換狀態(tài)的。在初始化階段,我們訂閱了closeend等回調(diào)。
    • this._socket.on("close",()=>this.transition(this.DISCONNECTED))
    • this._socket.on("end",()=>this.transition(this.DISCONNECTED))
    • this._socket.on("error",()=>this.transition(this.ERROR))

當(dāng)執(zhí)行socket.connect方法后,如果接收到close/end/error則會(huì)轉(zhuǎn)換到對(duì)應(yīng)的DISCONNECTEDERROR狀態(tài)。

  • 至此,實(shí)現(xiàn)了當(dāng)tcp.connect方法,狀態(tài)轉(zhuǎn)換到Connecting狀態(tài),連接成功轉(zhuǎn)換至Connected狀態(tài),連接被斷開轉(zhuǎn)換至Disconnected狀態(tài),出現(xiàn)錯(cuò)誤時(shí)轉(zhuǎn)換到ERROR狀態(tài)。并且在出錯(cuò)時(shí)會(huì)進(jìn)行一定重試操作,更多關(guān)于重試的內(nèi)容詳見后續(xù)介紹。

第四步:偵聽連接狀態(tài)

在TCP連接生命周期內(nèi),狀態(tài)機(jī)會(huì)在最后Initial/Connecting/Connected/Disconnecting/Disconnected/AlwaysDisconnected狀態(tài)之間進(jìn)行轉(zhuǎn)換,我們希望可能偵聽狀態(tài)機(jī)的狀態(tài)轉(zhuǎn)換事件,以便在連接發(fā)生狀態(tài)轉(zhuǎn)換時(shí)進(jìn)行一些操作,此時(shí)就可以偵聽各種連接事件。

偵聽連接狀態(tài)有兩種方法:

  • FlexStateMachine本身就是一個(gè)EventEmitter,可以通過訂閱事方式進(jìn)行偵聽。
// *****偵聽某個(gè)狀態(tài)事件*****tcp.on("Connected/enter",({from,to})=>{// 當(dāng)準(zhǔn)備進(jìn)入連接前狀態(tài)時(shí)觸發(fā)此事件
})      tcp.on("Connected/leave",({from,to})=>{// 當(dāng)準(zhǔn)備要離開連接狀態(tài)時(shí)觸發(fā)此事件
})  tcp.on("Connected/done",({from,to})=>{// 當(dāng)切換至連接狀態(tài)后觸發(fā)此事件
})   
  • 在類中也可以直接定義on<狀態(tài)名>Enteron<狀態(tài)名>、on<狀態(tài)名>Done、on<狀態(tài)名>Leave類方法來偵聽事件。
class TcpClient extends FlexStateMachine{onInitialEnter({from,to}){...}			// 進(jìn)入Initial狀態(tài)前onInitial({from,to}){...}					// 已切換至Initial狀態(tài)onInitialDone({from,to}){...}				// ===onInitialonInitialLeave({from,to}){...}		  	// 離開Initial狀態(tài)時(shí)onConnectingEnter({from,to}){...}			// 進(jìn)入Connecting狀態(tài)前onConnecting({from,to}){...}				// 已切換至Connecting狀態(tài)onConnectingDone({from,to}){...}      	// === onConnectingonConnectingLeave({from,to}){...}		  	// 離開Connecting狀態(tài)時(shí)onConnectedEnter({from,to}){...}			// 進(jìn)入Connected狀態(tài)前onConnected({from,to}){...}				// 已切換至Connected狀態(tài)onConnectedDone({from,to}){...}			// ===onConnectedonConnectedLeave({from,to}){...}		  	// 離開Connected狀態(tài)時(shí)//...所有狀態(tài)均可以定義on<狀態(tài)名>Enter、on<狀態(tài)名>、on<狀態(tài)名>Leave事件 }

第五步:斷開重新連接

連接管理中的斷開重連是非常重要的功能,要處理此邏輯,首先分析一下什么情況下會(huì)斷開連接。

斷開連接一般包括主動(dòng)被動(dòng)兩種情況:

  • 服務(wù)器或網(wǎng)絡(luò)問題等導(dǎo)致的連接斷開

此種情況屬于客戶端被動(dòng)斷開連接,一般會(huì)需要進(jìn)行自動(dòng)重新連接。服務(wù)器主動(dòng)斷開時(shí),客戶端會(huì)偵聽到end事件,直接進(jìn)入斷開狀態(tài)。即狀態(tài)機(jī)不會(huì)切換到Disconnecting,而是直接至Disconnected。

  • 客戶端主動(dòng)斷開連接

此種情況屬性客戶主動(dòng)斷開連接發(fā),就是客戶端主動(dòng)調(diào)用disconnect方法,一般是不需要進(jìn)行自動(dòng)重連的。
主動(dòng)斷開時(shí),需要調(diào)用socket.end方法,然后等待end事件的觸發(fā)。狀態(tài)機(jī)會(huì)經(jīng)歷從DisconnectingDisconnected的過程。

無論是主動(dòng)斷開連接還是被動(dòng)斷開連接,均會(huì)觸發(fā)close事件,因此需要在close事件觸發(fā)時(shí)區(qū)別是主動(dòng)斷開還是被動(dòng)斷開。
為了更好地區(qū)別主動(dòng)斷開被動(dòng)斷開,我們可以增加一個(gè)狀態(tài)AlwaysDisconnected來代表是客戶端主動(dòng)斷開,AlwaysDisconnected被設(shè)計(jì)為FINAL狀態(tài)。
當(dāng)狀態(tài)機(jī)切換到Disconnected狀態(tài)時(shí)調(diào)用connect動(dòng)作方法來重新連接。當(dāng)狀態(tài)機(jī)切換到AlwaysDisconnected時(shí),則不進(jìn)行重新連接。
兩者差別在于,如果是主動(dòng)斷開會(huì)經(jīng)歷Disconnecting狀態(tài),而被動(dòng)斷開則不會(huì)經(jīng)過此狀態(tài),因此我們就可以在on("close")事件中處理將狀態(tài)轉(zhuǎn)換至AlwaysDisconnectedDISCONNECTED

class TcpClient extends FlexStateMachine{class TcpClient extends FlexStateMachine{...// 轉(zhuǎn)換至Initial狀態(tài)前會(huì)調(diào)用方法async onInitialEnter({retry,retryCount}){// 在此需要確認(rèn)該切換到Disconnected還是AlwaysDisconnected狀態(tài)this._socket.on("close",()=>{// 主動(dòng)調(diào)用disconnect方法時(shí),狀態(tài)機(jī)才會(huì)切換到Disconnectingif(this.current.name==="Disconnecting"){ this.transition(this.ALWAYSDISCONNECTED)}else{this.transition(this.DISCONNECTED)}})}// 當(dāng)切換至Disconnected狀態(tài)的回調(diào)async onDisconnected({from,to}){await delay(3000)this.connect()								// 重新執(zhí)行Connect動(dòng)作}//async onConnectClosed({from,to}){}@state({when:"Connected",pending:"Disconnecting"// 由于調(diào)用end方法是異步操作,需要等待close事件觸發(fā)后,才是真正的斷開連接 // 因此,不能在調(diào)用disconnected返回后就將狀態(tài)設(shè)置為AlwaysDisconnected// 也就是說不要在此配置rejected參數(shù);// 假設(shè)執(zhí)行this._socket.end沒有出錯(cuò),則狀態(tài)將保持在Disconnecting狀態(tài),直至this._socket.on("close",callback)時(shí)才進(jìn)行狀態(tài)轉(zhuǎn)換// rejected:""  })async disconnect(){// 注意:此操作是異步狀態(tài)this._socket.end()   }
}

第六步:連接認(rèn)證子狀態(tài)

當(dāng)tcp連接成功后,一般服務(wù)器會(huì)要求對(duì)客戶連接進(jìn)行認(rèn)證才允許進(jìn)行使用,而認(rèn)證操作(login/logout)是一個(gè)耗時(shí)的異步操作,同樣需要進(jìn)行狀態(tài)管理。當(dāng)進(jìn)入Connected狀態(tài)后,狀態(tài)將在未認(rèn)證、正在認(rèn)證、已認(rèn)證三個(gè)狀態(tài)間進(jìn)行轉(zhuǎn)換,并且在連接斷開或者出錯(cuò)時(shí)馬上退出這三個(gè)狀態(tài)。因此,就有必要引入子狀態(tài)的概念。

引入子狀態(tài)后,對(duì)應(yīng)的狀態(tài)圖更新如下:

在這里插入圖片描述

class TcpClient extends FlexStateMachine{static states = { Connected		: { value:2, title:"已連接", next:["Disconnecting","Disconnected","Error"] // 定義一個(gè)獨(dú)立的狀態(tài)機(jī)域scope:{states:{Unauthenticated : {value:0,title:"未認(rèn)證",initial:true,next:["Authenticating"]},Authenticating  : {value:1,title:"正在認(rèn)證",next:["Authenticated"]}Authenticated   : {value:2,title:"已認(rèn)證",next:["Unauthenticated"]},}}},  }  ......// 當(dāng)狀態(tài)機(jī)進(jìn)入Connected后會(huì)啟動(dòng)其子狀態(tài)機(jī)// 子狀態(tài)機(jī)會(huì)轉(zhuǎn)換到其初始狀態(tài)Unauthenticated,然后就可以在此執(zhí)行登錄動(dòng)作async onUnauthenticatedEnter({from,to}){this.login()								// }onAuthenticated({from,to}){}@state({when:["Authenticating"],pending:["Authenticating"]})async login(){await this.send({// 認(rèn)證信息})}@state({when:["Authenticated"] })async logout(){await this.send({// 注銷信息})    }
}

推薦

以下是我的一大波開源項(xiàng)目推薦:

  • 全流程一健化React/Vue/Nodejs國(guó)際化方案 - VoerkaI18n
  • 無以倫比的React表單開發(fā)庫 - speedform
  • 終端界面開發(fā)增強(qiáng)庫 - Logsets
  • 簡(jiǎn)單的日志輸出庫 - VoerkaLogger
  • 裝飾器開發(fā) - FlexDecorators
  • 有限狀態(tài)機(jī)庫 - FlexState
  • 通用函數(shù)工具庫 - FlexTools
  • 小巧優(yōu)雅的CSS-IN-JS庫 - Styledfc
  • 為JSON文件添加注釋的VSCODE插件 - json_comments_extension
  • 開發(fā)交互式命令行程序庫 - mixed-cli
  • 強(qiáng)大的字符串插值變量處理工具庫 - flexvars
  • 前端link調(diào)試輔助工具 - yald
  • 異步信號(hào) - asyncsignal
http://www.risenshineclean.com/news/273.html

相關(guān)文章:

  • 企業(yè)網(wǎng)站建設(shè)話術(shù)/營(yíng)銷網(wǎng)站
  • wordpress pdf生成/手機(jī)端網(wǎng)站優(yōu)化
  • 工信部外國(guó)網(wǎng)站備案/b站在線觀看人數(shù)在哪
  • wordpress 時(shí)尚主題/駐馬店百度seo
  • 嘉興網(wǎng)站排名優(yōu)化價(jià)格/北京網(wǎng)站
  • 網(wǎng)站建設(shè)部門/網(wǎng)站軟件下載
  • 建立收費(fèi)網(wǎng)站/網(wǎng)絡(luò)銷售面試問題有哪些
  • 做搞基視頻網(wǎng)站/網(wǎng)絡(luò)營(yíng)銷的案例有哪些
  • 網(wǎng)站怎么做下載連接/百度長(zhǎng)尾關(guān)鍵詞挖掘
  • 網(wǎng)站彈窗客服代碼/刷推廣鏈接
  • 政府網(wǎng)站公眾號(hào)建設(shè)方案/谷歌瀏覽器 安卓下載2023版
  • wordpress tutorial/seo優(yōu)化排名服務(wù)
  • 網(wǎng)站被谷歌降權(quán)/廣州seo招聘網(wǎng)
  • 網(wǎng)站聊天怎么做/最新軍事報(bào)道
  • 成都微信端網(wǎng)站建/蘇州seo按天扣費(fèi)
  • 網(wǎng)站沒有百度快照/全網(wǎng)絡(luò)品牌推廣
  • 制作企業(yè)網(wǎng)站需要注意的事項(xiàng)/地推是什么
  • 資料填寫網(wǎng)站類型怎么做/新聞發(fā)稿公司
  • 免費(fèi)建網(wǎng)站撫順/win10優(yōu)化大師有用嗎
  • 萬盛網(wǎng)站建設(shè)公司/當(dāng)下最流行的營(yíng)銷方式
  • 下載好看影視大全極速版/seo是什么工作內(nèi)容
  • 重慶響應(yīng)式網(wǎng)站建設(shè)公司/哪個(gè)軟件可以自動(dòng)排名
  • python源碼分享網(wǎng)站/深度搜索
  • 龍華網(wǎng)站建設(shè)方案表/免費(fèi)海報(bào)模板網(wǎng)站
  • 關(guān)鍵詞seo優(yōu)化/優(yōu)化大師官方免費(fèi)下載
  • 百度指數(shù) 網(wǎng)站/杭州優(yōu)化公司哪家好
  • 哈爾濱市建設(shè)網(wǎng)站/寧波網(wǎng)絡(luò)推廣產(chǎn)品服務(wù)
  • 湛江網(wǎng)站建設(shè)哪家好/網(wǎng)絡(luò)營(yíng)銷公司全網(wǎng)推廣公司
  • 個(gè)人可以做淘寶客網(wǎng)站嗎/網(wǎng)絡(luò)營(yíng)銷首先要進(jìn)行
  • 免費(fèi)制作單頁的網(wǎng)站/媒體推廣