-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Implement async validation #1
Conversation
Hi, Bruno, Thanks for this great suggestion. For part 1, it's great, we all agree the reasons you mentioned, so the breaking change is OK. And we'd like to take the usage <string
keyName="text"
title="Text"
validation= {{
schema: {pattern: '^[a-zA-Z0-9]{4,10}$'} // JSONSchemaOptions
validator: ()=>() //ValidationFunction
errorMessage: "Error!"
}}
/> FYI, there is a better way that we can create the AJV instance of a field only once at the compile time (Canner has the compiler that transforms schema to component tree) instead of creating instance at every validation. But we will improve this later, your solution is great for now. For part2,
// the validator which returns string
function(value) {
if (!syncValidate(value)) {
return 'the value is invalid';
}
}
// the validator which returns promise of string
function(value) {
return asyncValidate(value)
.then(valid => {
if (!valid) {
return 'the value is invalid';
}
});
}
// the validator which use async/await
async function(value) {
const valid = await asyncValidate(value)
if (!valid) {
return 'the value is invalid';
}
}
// the validator which throws string
function(value) {
if (!syncValidate(value)) {
throw new Error('the value is invalid');
}
}
// the validator which returns promise of string
function(value) {
return asyncValidate(value)
.then(valid => {
if (!valid) {
throw new Error('the value is invalid');
}
});
}
// the validator which use async/await
async function(value) {
const valid = await asyncValidate(value)
if (!valid) {
throw new Error('the value is invalid');
}
}
// the unexpected error
function(value) {
const a = '123';
// throw an unexpected error, should be invalid
a(value);
}
Although, the better solution to handle the Error is that we provide a Summary
<string
keyName="text"
title="Text"
validation= {{
schema: {pattern: '^[a-zA-Z0-9]{4,10}$'} // JSONSchemaOptions
validator: ()=>() //ValidationFunction
errorMessage: "Error!"
}}
/>
How do you think? Thanks! |
因為擔心英文言不及意,請讓我用中文敘述一次。
會用第一個部分英文版本另外在 canner/canner 開個 issue,
第二部分會直接去編輯現有的那個 issue。
Part One
首先,validation 這個物件會整個過一次 ajv.compile(),再把 validator, errorMessage 從 validation 解構出來,在進行後續處理。這很明顯事先有 ajv驗證之後,錯誤訊息和自訂函數才陸陸續續加進來。
結論上,我覺得這種混在一起的方式相當不好,主要有幾個問題:
我覺得應該把會經過 ajv 的部分 跟我們自定義的 validator, errorMessage 有所區隔,方法大致有兩種。
一種是直接分成不同 props
另一種是還在同個props 但在物件中給予獨立的屬性:schema ( ajv 也是用這個關鍵字 )
只要用
const { schema, validator, errorMessage} = validation;
解構取值就好只要帶 schema 裡面的東西進去 compile 就好,如果沒 schema 的話連 ajv instance 都不用 new。
Part Two
再來是這次的主角: Async Validation
比較快的實作會是下面這樣直接套用 async/await 語法
當然會需要多一些驗證和例外處理,包含 Timeout 。尤其是 validator 帶進來的函式是第三方套件的狀況下。
不過看 canner 的 source code ,只有 server 端有用到 async / await 語法,不知道是不是怕過 babel 及 webpack 之後會有行為不如預習或有效能的考量?
有鑑於判斷到底是不是 async function/ function with promise return 是一件有點麻煩的事情,在瀏覽器端沒有除了runtime 判斷以外很好的跨瀏覽器解決方案。
極端而言甚至會有這兩種狀態:
如果純用 Promise 解決的情境,我偏好用 類似 Formik 原始碼 與 文件中這種不管哪種傳進來是不是回傳值帶 Promise 都先包一層起來的處理法。
包含原本的 ajv 驗證都 promise 化,用 promise.all 再把回傳值 map reduce的方式去處理,會比較清爽一點。
另外,因為是需要時間去處理的程序,可能需要一個地方或者就放在 error message 處,顯示驗證中 ( Validating... ) 的文字敘述,或者其他圖片動畫的示意。