مقالات

پیاده سازی یک کتابخانه ماشین حالت ساده در جاوا اسکریپت


“پیاده سازی یک کتابخانه ماشین پایانی ساده در جاوا اسکریپت” را در egghead.io تماشا کنید

اگر شما هم مثل من هستید، اولین باری که کلمه «ماشین دولتی» را شنیدید، خودتان بودید
کمی کنجکاو شدی و وقتی عمیق تر می شدی بیشتر از آن زمان گیج می شدی
شروع شده متوجه می شوم که وقتی با این موقعیت مواجه می شوم، پیاده سازی خودم را می نویسم
این مفهوم به تقویت آن برای من کمک می کند. پس این کاری است که ما می خواهیم انجام دهیم
با هم

من برای توضیح ماشین‌های حالت یا موارد استفاده از آن‌ها وقت صرف نمی‌کنم،
بنابراین شما باید پیدا کنید
منابع دیگر برای این اینجا
من فقط از طریق پیاده‌سازی ماشین حالت ساده توضیح خواهم داد شاید
به نظر می رسند من من استفاده از این پیاده سازی را در تولید توصیه نمی کنم. برای
این را ببینید xstate.

وب سایت عالی داره
(statecharts.github.io از
اریک موگنسن) که در آن می توانید چیزهای زیادی یاد بگیرید
این مفهوم “نمودار حالت” نامیده می شود. (نمودار حالت اساساً یک ماشین حالت است
با چند ویژگی اضافی و این چیز دیگری است که من توصیه می کنم
یادگیری در مورد.) یک صفحه عنوان در این وب سایت وجود دارد
ماشین دولتی چیست؟
جایی که می توانید اصول اولیه ماشین حالت را یاد بگیرید و اینجا کجاست
ما پارامترها (یا الزامات) را برای ماشین حالت خودمان جمع آوری می کنیم
عملکرد در اینجا برخی از آنها (برگرفته از سایت) آورده شده است:

  • یک حالت به این صورت تعریف می شود اولیه شرط هنگامی که یک ماشین شروع به
    اجرا کنید، به طور خودکار وارد این حالت می شود.
  • هر ایالت می تواند تعیین کند اقدامات که هنگام ورود یا خروج یک ماشین رخ می دهد
    این شرایط اقدامات معمولاً عوارض جانبی دارند.
  • هر حالت می تواند رویدادهایی را تعریف کند که باعث ایجاد a می شوند انتقال.
  • یک انتقال مشخص می‌کند که ماشین با خروج از آن رویداد، چگونه به آن واکنش نشان می‌دهد
    حالت و وارد شدن به حالتی دیگر.
  • انتقال می تواند تعیین کند اقدامات که در هنگام انتقال رخ می دهد.
    اقدامات معمولاً عوارض جانبی دارند.

همچنین، “وقتی یک رویداد رخ می دهد:”

  • رویداد در مقابل بررسی می شود وضعیت فعلی انتقال.
  • اگر یک انتقال با رویداد مطابقت داشته باشد، آن انتقال “اتفاق می افتد”.
  • به موجب “اتفاق” این گذار، دولت ها خارج شده و وارد می شوند
    اقدامات مناسب انجام می شود
  • دستگاه بلافاصله در است دولت جدید آماده پردازش بعدی است
    یک رویداد

خوب، بیایید شروع کنیم. بیایید با یک چیز ساده شروع کنیم. سوئیچ! آنجاست
کد شروع ما:

function createMachine(stateMachineDefinition) {
	const machine = {
		// machine object
	}
	return machine
}

// here's how we'll create the state machine
const machine = createMachine({
	// state machine definition object here...
})

// here's how we use the state machine
// comments are what we _want_ to have logged
let state = machine.value
console.log(`current state: ${state}`) // current state: off

state = machine.transition(state, 'switch')
console.log(`current state: ${state}`) // current state: on

state = machine.transition(state, 'switch')
console.log(`current state: ${state}`) // current state: off

ما با پر کردن شی تعریف ماشین حالت خود شروع می کنیم و سپس می توانیم
دریابیم که چگونه ماشین دولتی را وادار کنیم تا آنچه را که می خواهیم با آن انجام دهد
اطلاعات (افزودن: توسعه مبتنی بر API).

یک حالت به این صورت تعریف می شود اولیه شرط هنگامی که یک ماشین شروع به
اجرا کنید، به طور خودکار وارد این حالت می شود.

به اندازه کافی ساده است، ما از کاربر خواهیم داشت که این را به ما ارائه دهد initialState
مقدار باید:

const machine = createMachine({
	initialState: 'off',
})

و ما احتمالاً می خواهیم برای ایالت های خود نیز تعریفی داشته باشیم:

const machine = createMachine({
	initialState: 'off',
	off: {},
	on: {},
})

باشه عالیه به بعد:

هر ایالت می تواند تعیین کند اقدامات که هنگام ورود یا خروج یک ماشین رخ می دهد
این شرایط اقدامات معمولاً عوارض جانبی دارند.

بنابراین باید به کاربر اجازه دهیم تا تابعی را ارائه دهد که در صورت گنجاندن آن فراخوانی شود
ورود و خروج برای یک وضعیت معین:

const machine = createMachine({
	initialState: 'off',
	off: {
		actions: {
			onEnter() {},
			onExit() {},
		},
	},
	on: {
		actions: {
			onEnter() {},
			onExit() {},
		},
	},
})

و ما console.logs را اضافه می کنیم تا بتوانیم بعداً کار خود را بررسی کنیم.

const machine = createMachine({
	initialState: 'off',
	off: {
		actions: {
			onEnter() {
				console.log('off: onEnter')
			},
			onExit() {
				console.log('off: onExit')
			},
		},
	},
	on: {
		actions: {
			onEnter() {
				console.log('on: onEnter')
			},
			onExit() {
				console.log('on: onExit')
			},
		},
	},
})

باشه، حالا بعدش چیه؟

هر حالت می تواند رویدادهایی را تعریف کند که باعث ایجاد a می شوند انتقال.

خوب، بیایید a اضافه کنیم transitions ویژگی تعاریف دولت ما:

const machine = createMachine({
	initialState: 'off',
	off: {
		actions: {
			onEnter() {
				console.log('off: onEnter')
			},
			onExit() {
				console.log('off: onExit')
			},
		},
		transitions: {},
	},
	on: {
		actions: {
			onEnter() {
				console.log('on: onEnter')
			},
			onExit() {
				console.log('on: onExit')
			},
		},
		transitions: {},
	},
})

را off دولت باید بتواند به آن سوئیچ کند on وضعیت و ما با شما تماس خواهیم گرفت
این رویداد “تغییر” پس از آن on دولت باید بتواند به آن سوئیچ کند
off حالت نیز وجود دارد و منطقی است که آن را یک “سوئیچ” نیز بنامیم، پس بیایید
الف اضافه کنید switch دارایی ما transitions شیء:

const machine = createMachine({
	initialState: 'off',
	off: {
		actions: {
			onEnter() {
				console.log('off: onEnter')
			},
			onExit() {
				console.log('off: onExit')
			},
		},
		transitions: {
			switch: {},
		},
	},
	on: {
		actions: {
			onEnter() {
				console.log('on: onEnter')
			},
			onExit() {
				console.log('on: onExit')
			},
		},
		transitions: {
			switch: {},
		},
	},
})

زیبا و مورد بعدی:

یک انتقال مشخص می‌کند که ماشین با خروج از آن رویداد، چگونه به آن واکنش نشان می‌دهد
حالت و وارد شدن به حالتی دیگر.

خوب، پس من فکر می کنم ما می توانیم به یک اشاره کنیم target در مورد رویداد انتقال ما و زمان
این رویداد رخ می دهد، ماشین ما ما را از وضعیت فعلی انتقال می دهد
به حالت هدف:

const machine = createMachine({
	initialState: 'off',
	off: {
		actions: {
			onEnter() {
				console.log('off: onEnter')
			},
			onExit() {
				console.log('off: onExit')
			},
		},
		transitions: {
			switch: {
				target: 'on',
			},
		},
	},
	on: {
		actions: {
			onEnter() {
				console.log('on: onEnter')
			},
			onExit() {
				console.log('on: onExit')
			},
		},
		transitions: {
			switch: {
				target: 'off',
			},
		},
	},
})

عالی است، بنابراین زمانی که ماشین دولتی ما در آن است off شرایط و ما تماس می گیریم
machine.transition(state, 'switch') سپس باید از آن عبور کند off
دولت به on شرط وقتی به آن رسیدیم، این منطق را اعمال خواهیم کرد، اما شما باید ادامه دهید
تعریف ما شامل همه چیزهایی است که برای تحقق این امر لازم است.

خوب، بیایید آخرین مورد را برای تعریف بررسی کنیم:

انتقال می تواند تعیین کند اقدامات که در هنگام انتقال رخ می دهد.
اقدامات معمولاً عوارض جانبی دارند.

بر این اساس، وضعیت ورود/خروج ما می‌تواند اعمال داشته باشد و انتقال‌های ما می‌توانند
اقدامات نیز وجود دارد. در ابتدا وقتی این را خواندم گیج شدم زیرا چنین فکر می کردم
دو راه برای انجام یک کار مشابه، اما اگر این را در حالت واقعی تری به خاطر بسپارید
ماشین‌ها، ممکن است راه‌های زیادی برای ورود به یک حالت وجود داشته باشد، و شاید ما برخی از آنها را بخواهیم
عارضه جانبی تنها زمانی رخ می دهد که از یک حالت خاص B به حالت A منتقل می شود
اما نه از حالت C. پس بیایید اضافه کنیم action به مال ما transition اشیاء (i
ما console.log را در آنجا قرار می دهیم تا بعداً آن را زیر نظر داشته باشیم).

const machine = createMachine({
	initialState: 'off',
	off: {
		actions: {
			onEnter() {
				console.log('off: onEnter')
			},
			onExit() {
				console.log('off: onExit')
			},
		},
		transitions: {
			switch: {
				target: 'on',
				action() {
					console.log('transition action for "switch" in "off" state')
				},
			},
		},
	},
	on: {
		actions: {
			onEnter() {
				console.log('on: onEnter')
			},
			onExit() {
				console.log('on: onExit')
			},
		},
		transitions: {
			switch: {
				target: 'off',
				action() {
					console.log('transition action for "switch" in "on" state')
				},
			},
		},
	},
})

عالی ما یک API برای تعریف وضعیت شی ایجاد کرده ایم. حالا بیایید
اعمال کنید چه زمانی اتفاق می افتد transition نامیده می شود.

وقتی کاربر می خواهد ماشینی ایجاد کند، قبلاً این را به عنوان API مشخص کرده ایم:

const machine = createMachine({
	// state machine definition object
})

machine.value // current state
machine.transition(currentState, eventName)

از نظر فنی می‌توانیم ماشین حالت خود را به حالت پیش‌فرض در وضعیت فعلی قرار دهیم
machine.value، اما من این ایده را دوست دارم transition پذیرش وضعیت فعلی
توسط کاربر (و این همان کاری است که xstate انجام می دهد)، بنابراین ما با این کار خواهیم رفت.

بنابراین در اینجا چیزی است که ما برای استقرار اولیه خود نیاز داریم createMachine:

function createMachine(stateMachineDefinition) {
	const machine = {
		// machine object
	}
	return machine
}

بیایید جلو برویم و اضافه کنیم value و transition خواص:

function createMachine(stateMachineDefinition) {
	const machine = {
		value: stateMachineDefinition.initialState,
		transition(currentState, event) {
			return machine.value
		},
	}
	return machine
}

به یاد داشته باشید currentState چیزی شبیه به 'off' یا 'on' در مورد ما
و event خواهد بود 'switch' برای مثال سوئیچینگ ما

عالی است، حالا بیایید لیست را پایین بیاوریم و موارد را یکی یکی پیاده سازی کنیم:

رویداد در مقابل بررسی می شود وضعیت فعلی انتقال.

خوب، بیایید شی transitions را بگیریم و مقصد را تعریف کنیم
انتقال

function createMachine(stateMachineDefinition) {
	const machine = {
		value: stateMachineDefinition.initialState,
		transition(currentState, event) {
			const currentStateDefinition = stateMachineDefinition[currentState]
			const destinationTransition = currentStateDefinition.transitions[event]

			return machine.value
		},
	}
	return machine
}

برای روشن شدن، destinationTransition در این مرحله برای ما off -> on
انتقال خواهد بود:

{
  target: 'on',
  action() {
    console.log('transition action for "switch" in "off" state')
  },
}

بنابراین در اینجا ما با موفقیت به اطلاعات انتقال برای این کار دسترسی داریم
ترکیب فعلی وضعیت + رویداد.

اگر یک انتقال با رویداد مطابقت داشته باشد، آن انتقال “اتفاق می افتد”.

خوب، پس اگر کاربر با این رویداد یک انتقال از وضعیت فعلی تعریف کرده باشد،سپس ادامه می دهیم، در غیر این صورت زودتر از آن خارج می شویم:

function createMachine(stateMachineDefinition) {
	const machine = {
		value: stateMachineDefinition.initialState,
		transition(currentState, event) {
			const currentStateDefinition = stateMachineDefinition[currentState]
			const destinationTransition = currentStateDefinition.transitions[event]
			if (!destinationTransition) {
				return
			}

			return machine.value
		},
	}
	return machine
}

به موجب “اتفاق” این گذار، دولت ها خارج شده و وارد می شوند
اقدامات مناسب انجام می شود

خوب، پس باید با آن تماس بگیریم action برای انتقال، از onExit برای
وضعیت فعلی و onEnter برای حالت بعدی برای انجام این کار، ما نیز نیاز داریم
برای دریافت تعریف حالت مقصد نیز. بیایید همه اینها را انجام دهیم:

function createMachine(stateMachineDefinition) {
	const machine = {
		value: stateMachineDefinition.initialState,
		transition(currentState, event) {
			const currentStateDefinition = stateMachineDefinition[currentState]
			const destinationTransition = currentStateDefinition.transitions[event]
			if (!destinationTransition) {
				return
			}
			const destinationState = destinationTransition.target
			const destinationStateDefinition =
				stateMachineDefinition[destinationState]

			destinationTransition.action()
			currentStateDefinition.actions.onExit()
			destinationStateDefinition.actions.onEnter()

			return machine.value
		},
	}
	return machine
}

و در نهایت:

دستگاه بلافاصله در است دولت جدید آماده پردازش بعدی است
یک رویداد

ما باید مقدار ماشین را که هست به روز کنیم target برای انتقال
(که ما به آن اختصاص دادیم destinationState متغیر):

function createMachine(stateMachineDefinition) {
	const machine = {
		value: stateMachineDefinition.initialState,
		transition(currentState, event) {
			const currentStateDefinition = stateMachineDefinition[currentState]
			const destinationTransition = currentStateDefinition.transitions[event]
			if (!destinationTransition) {
				return
			}
			const destinationState = destinationTransition.target
			const destinationStateDefinition =
				stateMachineDefinition[destinationState]

			destinationTransition.action()
			currentStateDefinition.actions.onExit()
			destinationStateDefinition.actions.onEnter()

			machine.value = destinationState

			return machine.value
		},
	}
	return machine
}

خوب، اینجاست:

function createMachine(stateMachineDefinition) {
	const machine = {
		value: stateMachineDefinition.initialState,
		transition(currentState, event) {
			const currentStateDefinition = stateMachineDefinition[currentState]
			const destinationTransition = currentStateDefinition.transitions[event]
			if (!destinationTransition) {
				return
			}
			const destinationState = destinationTransition.target
			const destinationStateDefinition =
				stateMachineDefinition[destinationState]

			destinationTransition.action()
			currentStateDefinition.actions.onExit()
			destinationStateDefinition.actions.onEnter()

			machine.value = destinationState

			return machine.value
		},
	}
	return machine
}

const machine = createMachine({
	initialState: 'off',
	off: {
		actions: {
			onEnter() {
				console.log('off: onEnter')
			},
			onExit() {
				console.log('off: onExit')
			},
		},
		transitions: {
			switch: {
				target: 'on',
				action() {
					console.log('transition action for "switch" in "off" state')
				},
			},
		},
	},
	on: {
		actions: {
			onEnter() {
				console.log('on: onEnter')
			},
			onExit() {
				console.log('on: onExit')
			},
		},
		transitions: {
			switch: {
				target: 'off',
				action() {
					console.log('transition action for "switch" in "on" state')
				},
			},
		},
	},
})

let state = machine.value
console.log(`current state: ${state}`)
state = machine.transition(state, 'switch')
console.log(`current state: ${state}`)
state = machine.transition(state, 'switch')
console.log(`current state: ${state}`)

و اگر بخواهید این مورد را در Chrome DevTools خود ظاهر کنید، در اینجا گزارش هایی وجود دارد که باید ایجاد کنید
دریافت کنید:

current state: off
transition action for "switch" in "off" state
off: onExit
on: onEnter
current state: on
transition action for "switch" in "on" state
on: onExit
off: onEnter
current state: off

و شما می توانید با آن بازی کنید
در Codesandbox

امیدوارم برای شما جالب، آموزنده و سرگرم کننده بوده باشد. اگر شما هستید
من واقعاً می خواهم بیشتر در این چیزها غوطه ور شوم، سپس قطعاً می دهم
statecharts.github.io نگاه کنید و بدهید
دیوید خورشید را دنبال کنید. او در خصوصی است
ماموریت این است که ماشین آلات دولتی را در دسترس‌تر و در اختیار خودم قرار دهم
علاقه به مفهوم

موفق باشید!


Source link

نوشته های مشابه

دیدگاهتان را بنویسید

همچنین ببینید
بستن
دکمه بازگشت به بالا