ඇද වැටෙනු එපා පුස්තකාල සියල්ල ඉටු කරන ආකාරය නියම කළ යුතු හිතන උගුලක් . ඔබට ජාවාස්ක්රිප්ට් හි කල් ඉකුත් වීමක් සමඟ යමක් කිරීමට අවශ්ය නම්, ඔබ භාවිතා කළ setTimeout
යුතුය. Redux ක්රියා වෙනස් විය යුතු බවට කිසිදු හේතුවක් නැත.
Redux කරයි අසමමුහුර්ත දේවල් සමඟ ගනුදෙනු කිරීමේ විකල්ප ක්රම කිහිපයක් ඉදිරිපත් කරයි, නමුත් ඔබ ඒවා භාවිතා කළ යුත්තේ ඔබ ඕනෑවට වඩා කේත පුනරාවර්තනය කරන බව දැනගත් විට පමණි. ඔබට මෙම ගැටළුව නොමැති නම්, භාෂාව ඉදිරිපත් කරන දේ භාවිතා කර සරලම විසඳුම සඳහා යන්න.
අසින්ක් කේත පේළිය ලිවීම
මෙය බොහෝ දුරට සරලම ක්රමයයි. මෙහි Redux සඳහා විශේෂිත කිසිවක් නොමැත.
store.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' })
setTimeout(() => {
store.dispatch({ type: 'HIDE_NOTIFICATION' })
}, 5000)
ඒ හා සමානව, සම්බන්ධිත අංගයක් ඇතුළත සිට:
this.props.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' })
setTimeout(() => {
this.props.dispatch({ type: 'HIDE_NOTIFICATION' })
}, 5000)
එකම වෙනස වන්නේ සම්බන්ධිත සංරචකයක් තුළ ඔබට සාමාන්යයෙන් ගබඩාවට ප්රවේශය නොමැති නමුත් dispatch()
මුක්කු ලෙස එන්නත් කිරීම හෝ විශේෂිත ක්රියාකාරී නිර්මාණකරුවන් ලබා ගැනීමයි . කෙසේ වෙතත් මෙය අපට කිසිදු වෙනසක් නොකරයි.
එකම ක්රියාවන් විවිධ සංරචක වලින් පිටත් කර යැවීමේදී යතුරු ලියනය කිරීමට ඔබ අකමැති නම්, ක්රියාකාරී වස්තු පේළිගත කිරීම වෙනුවට ක්රියාකාරී නිර්මාණකරුවන් උපුටා ගැනීමට ඔබට අවශ්ය විය හැකිය:
// actions.js
export function showNotification(text) {
return { type: 'SHOW_NOTIFICATION', text }
}
export function hideNotification() {
return { type: 'HIDE_NOTIFICATION' }
}
// component.js
import { showNotification, hideNotification } from '../actions'
this.props.dispatch(showNotification('You just logged in.'))
setTimeout(() => {
this.props.dispatch(hideNotification())
}, 5000)
නැතහොත්, ඔබ මීට පෙර ඒවා සමඟ බැඳී ඇත්නම් connect()
:
this.props.showNotification('You just logged in.')
setTimeout(() => {
this.props.hideNotification()
}, 5000)
මෙතෙක් අපි කිසිදු මිඩ්ල්වෙයාර් හෝ වෙනත් උසස් සංකල්පයක් භාවිතා කර නොමැත.
අසින්ක් ක්රියාකාරී නිර්මාතෘ උපුටා ගැනීම
ඉහත ප්රවේශය සරල අවස්ථාවන්හිදී හොඳින් ක්රියාත්මක වන නමුත් එයට ගැටළු කිහිපයක් ඇති බව ඔබට පෙනී යනු ඇත:
- ඔබට දැනුම් දීමක් පෙන්වීමට අවශ්ය ඕනෑම තැනක මෙම තර්කනය අනුපිටපත් කිරීමට එය බල කරයි.
- දැනුම්දීම්වල හැඳුනුම්පත් නොමැති බැවින් ඔබ දැනුම්දීම් දෙකක් වේගයෙන් පෙන්වන්නේ නම් ඔබට ධාවන තත්වයක් ඇත. පළමු කල් ඉකුත්වීම අවසන් වූ විට, එය යවනු ලැබේ
HIDE_NOTIFICATION
, කල් ඉකුත් වූ විගසම දෙවන දැනුම්දීම වැරදියට සඟවයි.
මෙම ගැටළු නිරාකරණය කිරීම සඳහා, කල් ඉකුත් වීමේ තර්කනය කේන්ද්රගත කර එම ක්රියාවන් දෙක යවන ශ්රිතයක් උකහා ගැනීමට ඔබට අවශ්ය වනු ඇත. එය මේ වගේ විය හැකිය:
// actions.js
function showNotification(id, text) {
return { type: 'SHOW_NOTIFICATION', id, text }
}
function hideNotification(id) {
return { type: 'HIDE_NOTIFICATION', id }
}
let nextNotificationId = 0
export function showNotificationWithTimeout(dispatch, text) {
// Assigning IDs to notifications lets reducer ignore HIDE_NOTIFICATION
// for the notification that is not currently visible.
// Alternatively, we could store the timeout ID and call
// clearTimeout(), but we’d still want to do it in a single place.
const id = nextNotificationId++
dispatch(showNotification(id, text))
setTimeout(() => {
dispatch(hideNotification(id))
}, 5000)
}
showNotificationWithTimeout
මෙම තර්කනය අනුපිටපත් නොකර හෝ විවිධ දැනුම්දීම් සහිත ධාවන තත්වයන් නොමැතිව දැන් සංරචක භාවිතා කළ හැකිය :
// component.js
showNotificationWithTimeout(this.props.dispatch, 'You just logged in.')
// otherComponent.js
showNotificationWithTimeout(this.props.dispatch, 'You just logged out.')
පළමු තර්කය ලෙස showNotificationWithTimeout()
පිළිගන්නේ ඇයි dispatch
? එයට හේතුව ක්රියාවන් ගබඩාවට යැවිය යුතු බැවිනි. සාමාන්යයෙන් සංරචකයකට ප්රවේශය ඇත, dispatch
නමුත් පිටත් කර යැවීම පාලනය කිරීම සඳහා බාහිර ශ්රිතයක් අපට අවශ්ය බැවින්, අප එය යැවීම පාලනය කළ යුතුය.
ඔබට මොඩියුලයකින් අපනයනය කරන ලද සිංගල්ටන් වෙළඳසැලක් තිබේ නම්, ඔබට එය ආනයනය dispatch
කර ඒ වෙනුවට කෙලින්ම එය කළ හැකිය:
// store.js
export default createStore(reducer)
// actions.js
import store from './store'
// ...
let nextNotificationId = 0
export function showNotificationWithTimeout(text) {
const id = nextNotificationId++
store.dispatch(showNotification(id, text))
setTimeout(() => {
store.dispatch(hideNotification(id))
}, 5000)
}
// component.js
showNotificationWithTimeout('You just logged in.')
// otherComponent.js
showNotificationWithTimeout('You just logged out.')
මෙය සරල බව පෙනේ, නමුත් අපි මෙම ප්රවේශය නිර්දේශ නොකරමු . අප එයට අකමැති වීමට ප්රධාන හේතුව එය ගබඩාව තනි පුද්ගලයකු වීමට බල කරන බැවිනි . මෙය සේවාදායක විදැහුම්කරණය ක්රියාත්මක කිරීම ඉතා අපහසු කරයි . සේවාදායකයේ, එක් එක් ඉල්ලීමට තමන්ගේම ගබඩාවක් තිබීම ඔබට අවශ්ය වනු ඇත, එවිට විවිධ පරිශීලකයින්ට විවිධ පූර්ව පැටවූ දත්ත ලැබෙනු ඇත.
සිංගල්ටන් වෙළඳසැලක් ද පරීක්ෂා කිරීම දුෂ්කර කරයි. ක්රියාකාරී නිර්මාණකරුවන් පරීක්ෂා කිරීමේදී ඔබට තවදුරටත් ගබඩාවක් සමච්චලයට ලක් කළ නොහැක, මන්ද ඔවුන් නිශ්චිත මොඩියුලයකින් අපනයනය කරන ලද නිශ්චිත සැබෑ වෙළඳසැලක් ගැන සඳහන් කරයි. ඔබට එහි තත්වය පිටතින් නැවත සැකසිය නොහැක.
එබැවින් ඔබට තාක්ෂණිකව මොඩියුලයකින් සිංගල්ටන් වෙළඳසැලක් අපනයනය කළ හැකි අතර, අපි එය අධෛර්යමත් කරමු. ඔබගේ යෙදුම කිසි විටෙකත් සේවාදායක විදැහුම්කරණය එකතු නොකරන බවට ඔබට විශ්වාස නම් මිස මෙය නොකරන්න.
පෙර අනුවාදය වෙත ආපසු යාම:
// actions.js
// ...
let nextNotificationId = 0
export function showNotificationWithTimeout(dispatch, text) {
const id = nextNotificationId++
dispatch(showNotification(id, text))
setTimeout(() => {
dispatch(hideNotification(id))
}, 5000)
}
// component.js
showNotificationWithTimeout(this.props.dispatch, 'You just logged in.')
// otherComponent.js
showNotificationWithTimeout(this.props.dispatch, 'You just logged out.')
මෙය තර්කනයේ අනුපිටපත් කිරීමේ ගැටළු විසඳන අතර ජාතියේ තත්වයන්ගෙන් අපව ගලවා ගනී.
Thunk Middleware
සරල යෙදුම් සඳහා, ප්රවේශය ප්රමාණවත් විය යුතුය. මිඩ්ල්වෙයාර් ගැන ඔබ සතුටු වන්නේ නම් ඒ ගැන කරදර නොවන්න.
කෙසේ වෙතත්, විශාල යෙදුම් වල, ඔබට එය වටා යම් යම් අපහසුතා ඇති විය හැකිය.
නිදසුනක් වශයෙන්, අප පසුකර යාම අවාසනාවක් සේ පෙනේ dispatch
. මෙමඟින් බහාලුම් සහ ඉදිරිපත් කිරීමේ සංරචක වෙන් කිරීම උපක්රමශීලී වේ. මන්දයත් රෙඩක්ස් ක්රියාවන් ඉහත ආකාරයට සමමුහුර්තව යවන ඕනෑම අංගයක් dispatch
මුක්කු ලෙස පිළිගත යුතු බැවින් එය තවදුරටත් සම්මත කළ හැකිය. ඔබට ක්රියා නිර්මාපකයින් connect()
තවදුරටත් බැඳ තැබිය නොහැක showNotificationWithTimeout()
. එය Redux ක්රියාවක් ලබා නොදේ.
ඊට අමතරව, සමමුහුර්ත ක්රියාකාරී නිර්මාපකයින් කැමති showNotification()
සහ අසමමුහුර්ත උදව්කරුවන් කැමති කුමන කාර්යයන්දැයි මතක තබා ගැනීම අමුතු දෙයක් විය හැකිය showNotificationWithTimeout()
. ඔබ ඒවා වෙනස් ලෙස භාවිතා කළ යුතු අතර ඒවා එකිනෙකා සමඟ වරදවා වටහා නොගැනීමට වගබලා ගන්න.
සහායක ශ්රිතයක් සඳහා මෙම රටාව “නීත්යානුකූල” කිරීමට ක්රමයක් සෙවීමේdispatch
අභිප්රේරණය මෙය වූ අතර , සම්පූර්ණයෙන්ම වෙනස් ක්රියාකාරිත්වයන්ට වඩා සාමාන්ය ක්රියාකාරී නිර්මාණකරුවන්ගේ විශේෂ අවස්ථාවක් ලෙස සමමුහුර්ත ක්රියාකාරී නිර්මාණකරුවන් “දැකීමට” රෙඩක්ස් හට උදව් කරයි.
ඔබ තවමත් අප සමඟ සිටී නම් සහ ඔබගේ යෙදුමේ ගැටලුවක් ලෙස ඔබ හඳුනා ගන්නේ නම්, Redux Thunk middleware භාවිතා කිරීමට ඔබව සාදරයෙන් පිළිගනිමු .
සාරාංශයක් තුළ, ඇත්ත වශයෙන්ම ක්රියාකාරී වන විශේෂ ක්රියා හඳුනා ගැනීමට Redux Thunk Redux හට උගන්වයි:
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
const store = createStore(
reducer,
applyMiddleware(thunk)
)
// It still recognizes plain object actions
store.dispatch({ type: 'INCREMENT' })
// But with thunk middleware, it also recognizes functions
store.dispatch(function (dispatch) {
// ... which themselves may dispatch many times
dispatch({ type: 'INCREMENT' })
dispatch({ type: 'INCREMENT' })
dispatch({ type: 'INCREMENT' })
setTimeout(() => {
// ... even asynchronously!
dispatch({ type: 'DECREMENT' })
}, 1000)
})
මෙම මිඩ්ල්වෙයාර් සක්රිය කර ඇති විට, ඔබ ශ්රිතයක් යවන්නේ නම්, රෙඩක්ස් තන්ක් මිඩ්ල්වෙයාර් එය dispatch
තර්කයක් ලෙස ලබා දෙනු ඇත. එමඟින් එවැනි ක්රියා “ගිල දමනු ඇත” එබැවින් ඔබේ අඩු කරන්නන්ට අමුතු ක්රියාකාරී තර්ක ලැබීම ගැන කරදර නොවන්න. ඔබේ අඩු කරන්නන්ට ලැබෙන්නේ සරල වස්තු ක්රියා පමණි - ඒවා සෘජුවම විමෝචනය වේ, නැතහොත් අප විස්තර කළ පරිදි ශ්රිත මඟින් විමෝචනය වේ.
මෙය එතරම් ප්රයෝජනවත් නොවන බව පෙනේ ද? මෙම විශේෂිත තත්වය තුළ නොවේ. කෙසේ වෙතත් එය showNotificationWithTimeout()
සාමාන්ය Redux ක්රියාකාරී නිර්මාපකයෙකු ලෙස ප්රකාශ කිරීමට අපට ඉඩ දෙයි :
// actions.js
function showNotification(id, text) {
return { type: 'SHOW_NOTIFICATION', id, text }
}
function hideNotification(id) {
return { type: 'HIDE_NOTIFICATION', id }
}
let nextNotificationId = 0
export function showNotificationWithTimeout(text) {
return function (dispatch) {
const id = nextNotificationId++
dispatch(showNotification(id, text))
setTimeout(() => {
dispatch(hideNotification(id))
}, 5000)
}
}
පෙර කොටසේ අප විසින් ලියන ලද ශ්රිතයට බොහෝ දුරට සමාන වන ආකාරය සැලකිල්ලට ගන්න. කෙසේ වෙතත් එය dispatch
පළමු තර්කය ලෙස පිළිගන්නේ නැත . ඒ වෙනුවට එය පළමු තර්කය ලෙස පිළිගන්නා ශ්රිතයක් නැවත ලබා දෙයිdispatch
.
අපගේ සංරචකයේ එය භාවිතා කරන්නේ කෙසේද? නිසැකවම, අපට මෙය ලිවිය හැකිය:
// component.js
showNotificationWithTimeout('You just logged in.')(this.props.dispatch)
අපි අවශ්ය වන්නේ අභ්යන්තර ක්රියාකාරිත්වය සාධාරණ ලෙස ලබා ගැනීම සඳහා අපි අසින්ක් ක්රියාකාරී නිර්මාතෘට කතා කර dispatch
පසුව සමත් වෙමු dispatch
.
කෙසේ වෙතත් මෙය මුල් අනුවාදයට වඩා අමුතුයි! ඇයි අපි ඒ පැත්තට ගියේ?
මම කලින් ඔබට කී දේ නිසා. Redux Thunk middleware සක්රීය කර ඇත්නම්, ඔබ ක්රියාකාරී වස්තුවක් වෙනුවට ශ්රිතයක් යැවීමට උත්සාහ කරන ඕනෑම වේලාවක, මිඩ්ල්වෙයාර් එම ශ්රිතය dispatch
ක්රමවේදය සමඟ පළමු තර්කය ලෙස හඳුන්වනු ඇත .
එබැවින් අපට ඒ වෙනුවට මෙය කළ හැකිය:
// component.js
this.props.dispatch(showNotificationWithTimeout('You just logged in.'))
අවසාන වශයෙන්, අසමමුහුර්ත ක්රියාවක් යැවීම (සැබවින්ම, ක්රියා මාලාවක්) එක් ක්රියාවක් සමමුහුර්තව සංරචකයට යැවීමට වඩා වෙනස් නොවේ. යම් දෙයක් සමමුහුර්තව හෝ සමමුහුර්තව සිදුවන්නේද යන්න සංරචක නොසලකන හෙයින් එය හොඳයි. අපි එය වියුක්ත කළා.
එවැනි “විශේෂ” ක්රියාකාරී නිර්මාණකරුවන් හඳුනා ගැනීමට අපි රෙඩක්ස් “ඉගැන්වූ” බැවින් (අපි ඔවුන්ව මෝඩ ක්රියාකාරී නිර්මාණකරුවන් ලෙස හඳුන්වන්නෙමු ), දැන් අපට නිත්ය ක්රියාකාරී නිර්මාණකරුවන් භාවිතා කරන ඕනෑම ස්ථානයක ඒවා භාවිතා කළ හැකිය. උදාහරණයක් ලෙස, අපට ඒවා භාවිතා කළ හැකිය connect()
:
// actions.js
function showNotification(id, text) {
return { type: 'SHOW_NOTIFICATION', id, text }
}
function hideNotification(id) {
return { type: 'HIDE_NOTIFICATION', id }
}
let nextNotificationId = 0
export function showNotificationWithTimeout(text) {
return function (dispatch) {
const id = nextNotificationId++
dispatch(showNotification(id, text))
setTimeout(() => {
dispatch(hideNotification(id))
}, 5000)
}
}
// component.js
import { connect } from 'react-redux'
// ...
this.props.showNotificationWithTimeout('You just logged in.')
// ...
export default connect(
mapStateToProps,
{ showNotificationWithTimeout }
)(MyComponent)
තන්ක්ස් වල රාජ්ය කියවීම
සාමාන්යයෙන් ඔබේ අඩු කරන්නන්ගේ ඊළඟ තත්වය තීරණය කිරීම සඳහා ව්යාපාර තර්කනය අඩංගු වේ. කෙසේ වෙතත්, අඩු කරන්නන් ක්රියා කරන්නේ පිටත් කිරීමෙන් පසුව පමණි. ඔබ ක්රියාකාරී ක්රියාකාරී නිර්මාපකයෙකු තුළ අතුරු ආබාධයක් (API එකක් ඇමතීම වැනි) ඇත්නම් සහ යම් කොන්දේසියක් යටතේ එය වළක්වා ගැනීමට ඔබට අවශ්ය නම් කුමක් කළ යුතුද?
තණ්ඩ මිඩ්ල්වෙයාර් භාවිතා නොකර, ඔබ මෙම පරීක්ෂණය සංරචකය තුළ සිදු කරයි:
// component.js
if (this.props.areNotificationsEnabled) {
showNotificationWithTimeout(this.props.dispatch, 'You just logged in.')
}
කෙසේ වෙතත්, ක්රියාකාරී නිර්මාණකරුවෙකු උපුටා ගැනීමේ කාරණය වූයේ මෙම පුනරාවර්තන තර්කනය බොහෝ සංරචක හරහා කේන්ද්රගත කිරීමයි. වාසනාවකට මෙන්, Redux වෙළඳසැලේ වත්මන් තත්වය කියවීමට Redux Thunk ඔබට ක්රමයක් සපයයි . ඊට අමතරව dispatch
, එය getState
ඔබගේ ක්රියාකාරී ක්රියාකාරී නිර්මාතෘ වෙතින් ඔබ ආපසු එන ශ්රිතයේ දෙවන තර්කය ලෙසද ගමන් කරයි . මෙමඟින් ගබඩාවේ වත්මන් තත්වය කියවීමට මාපටැඟිල්ලට ඉඩ දෙයි.
let nextNotificationId = 0
export function showNotificationWithTimeout(text) {
return function (dispatch, getState) {
// Unlike in a regular action creator, we can exit early in a thunk
// Redux doesn’t care about its return value (or lack of it)
if (!getState().areNotificationsEnabled) {
return
}
const id = nextNotificationId++
dispatch(showNotification(id, text))
setTimeout(() => {
dispatch(hideNotification(id))
}, 5000)
}
}
මෙම රටාව අනිසි ලෙස භාවිතා නොකරන්න. හැඹිලි දත්ත ඇති විට ඒපීඅයි ඇමතුම් සඳහා ඇප ලබා ගැනීම හොඳ ය, නමුත් ඔබේ ව්යාපාර තර්කනය ගොඩනඟා ගැනීමට එය හොඳ පදනමක් නොවේ. ඔබ getState()
විවිධ ක්රියා කොන්දේසි සහිතව යැවීමට පමණක් භාවිතා කරන්නේ නම් , ඒ වෙනුවට ව්යාපාර තර්කනය අඩු කරන්නන්ට ඇතුළත් කිරීම ගැන සලකා බලන්න.
ඊළඟ පියවර
දැන් ඔබට කපටිකම් ක්රියා කරන ආකාරය පිළිබඳ මූලික අවබෝධයක් තිබේ නම්, ඒවා භාවිතා කරන Redux async උදාහරණය බලන්න .
පොරොන්දම් ආපසු ලබා දෙන බොහෝ උදාහරණ ඔබට සොයාගත හැකිය. මෙය අවශ්ය නොවන නමුත් ඉතා පහසු විය හැකිය. Redux ඔබ මෝඩයෙකුගෙන් ආපසු එන්නේ කුමක් දැයි ගණන් ගන්නේ නැත, නමුත් එය ඔබට එහි ප්රතිලාභ වටිනාකම ලබා දෙයි dispatch()
. මේ නිසා ඔබට පොරොන්දුවක් ආපසු ලබා දිය හැකි අතර ඇමතුමෙන් එය සම්පූර්ණ වන තෙක් බලා සිටින්න dispatch(someThunkReturningPromise()).then(...)
.
ඔබට සංකීර්ණ thunk action creators කුඩා thunk action creators කිහිපයකට බෙදිය හැකිය. මෙම dispatch
ඔබ ඇත්තෙන් වෙනසට භාජනය රටාව ඉල්ලුම් කළ හැකි නිසා thunks විසින් සපයන ක්රමය, ම thunks භාර කළ හැකිය. නැවතත්, මෙය පොරොන්දු සමඟ වඩාත් හොඳින් ක්රියාත්මක වන්නේ ඔබට ඒ මත අසමමුහුර්ත පාලන ප්රවාහයක් ක්රියාත්මක කළ හැකි බැවිනි.
සමහර යෙදුම් සඳහා, ඔබේ අසමමුහුර්ත පාලන ප්රවාහ අවශ්යතා තන්ක සමඟ ප්රකාශ කළ නොහැකි තරම් සංකීර්ණ තත්වයකට ඔබ පත්විය හැකිය. නිදසුනක් ලෙස, අසාර්ථක ඉල්ලීම් නැවත උත්සාහ කිරීම, ටෝකන සමඟ නැවත බලය පැවරීම හෝ පියවරෙන් පියවර යතුරු පුවරුව මේ ආකාරයෙන් ලිවීමේදී වාචික හා දෝෂ සහිත විය හැකිය. මෙම අවස්ථාවේදී, ඔබට Redux Saga හෝ Redux Loop වැනි වඩා දියුණු අසමමුහුර්ත පාලන ප්රවාහ විසඳුම් දෙස බැලීමට අවශ්ය විය හැකිය . ඒවා ඇගයීමට ලක් කරන්න, ඔබේ අවශ්යතාවන්ට අදාළ උදාහරණ සංසන්දනය කර ඔබ වඩාත්ම කැමති දේ තෝරා ගන්න.
අවසාන වශයෙන්, ඔබට ඒවා සඳහා අව්යාජ අවශ්යතාවයක් නොමැති නම් (කටු ඇතුළු) කිසිවක් භාවිතා නොකරන්න. අවශ්යතා මත පදනම්ව, ඔබේ විසඳුම තරම් සරල බව මතක තබා ගන්න
store.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' })
setTimeout(() => {
store.dispatch({ type: 'HIDE_NOTIFICATION' })
}, 5000)
ඔබ මෙය කරන්නේ ඇයි දැයි ඔබ දන්නේ නැත්නම් එය දහඩිය දමන්න එපා.
redux-saga
ඔබට වඩා හොඳ යමක් අවශ්ය නම් මගේ පදනම් පිළිතුර පරීක්ෂා කිරීමට අමතක නොකරන්න . ප්රමාද පිළිතුර නිසා එය දිස්වීමට පෙර ඔබට බොහෝ වේලාවක් අනුචලනය කළ යුතුය :) එයින් කියවෙන්නේ එය කියවීම වටී නැති බවයි. මෙන්න කෙටිමඟක්: stackoverflow.com/a/38574266/82609