node.js - mysql sorgu sonuçlarını TypeScript Nesnelerine doğru bir şekilde nasıl ayrıştırılır
Şu anda TypeScript ile bazı middleware yazıyorum (JavaScript'e derleniyor ve NodeJS üzerinde çalışıyor). Bu middleware çoğu durumda Typeorm kullanıyor. Ama bazen SQL ile çılgın şeyler yapmak isteyebilirsiniz. Bu yüzden ham SQL sorguları gönderen ve onları şöyle döndüren bazı kodlar yazdım:
public query(query: string): Promise<RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[]> {
return new Promise<RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[]>((resolve, reject) => {
this.status = DBCstatus.busy;
this.mysqlConnection.query(query, (err, result, fields)=> {
this.lastAnswerTime = Date.now();
if (err === null) {
this.status = DBCstatus.open;
resolve(result)
} else {
reject(err);
}
})
})
}
Şu ana kadar her şey yolunda değil mi?
Pek sayılmaz. Bu fonksiyonun her kullanıcısı, aslında bu yanıtın içinde ne olduğunu kontrol etmek zorunda kalır.
Ne istiyorum
İki temel işlev arasında seçim yapabilmeliyim:
- Sorguları Seç
- Güncelle/Ekle vs.
Hadi bu şekilde kullanılacak olan fonksiyona odaklanalım:
let cars: cars[] = await queryForData<cars>("Select * from cars");
Şu ana kadar elde ettiklerim
public queryForData<t>(query: string): Promise<t[]> {
return new Promise<t[]>( async (resolve, reject) => {
let queryResult: RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[];
let dataFromQuery: t[] = [];
try {
queryResult = await this.query(query);
if (queryResult instanceof Array) {
if (queryResult.length > 0) {
if (queryResult[0].constructor.name === QueryResultType.textRow) {
let rowData: t[] = queryResult as t[];
return rowData;
} else {
reject(QueryError.unexpectedQueryResult)
}
} else {
resolve(dataFromQuery);
}
} else {
reject(QueryError.unexpectedQueryResult)
}
resolve([]);
} catch(error) {
reject(error);
}
})
}
Tamam harika, işe yarıyor! Peki o zaman sorunun ne?
Fonksiyonu şöyle kullanacak olursam:
let foo: Foo[] = await queryForData<Foo>("Select * from Bar");
Bu da işe yarardı çünkü TypeScript, Foo tanımının Bar ile eşleşip eşleşmeyeceğini kontrol etmezdi. Yani foo ile çalışırken daha sonra hatalar olurdu.
Ne yapılabilir?
public queryForData<t>( example: t, query: string): Promise<t[]> {
let queryResult: RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[];
queryResult = await this.query(query);
if (queryResult instanceof Array) {
if (queryResult.length > 0) {
for (let attr in example) {
// basicly
if (queryResult[0][attr] === undefined) {
// error
}
}
}
}
Bu, işleri yapmanın doğru bir yolu olur mu? Veritabanının modelini bildiğim için bu aşırıya kaçmak olur mu? Her zaman olduğu gibi şimdiden teşekkürler!
OCAK 2021 GÜNCELLEME
Son birkaç ay içinde, ihtiyaçlarım için bilinmeyen nesneleri doğrulamanın bir yolunu buldum. Nesnede açıklamalar kullandım. Kendi veritabanımı kullanırken modelin önceden bilinmesi nedeniyle bunun fazla olduğunu düşündüm ama üçüncü taraf arayüzleri veya veritabanlarını kullanırken oldukça faydalı oldu. Ben bunu nasıl yaptığımı görmek isterseniz, buradan inceleyebilirsiniz: https://github.com/SpaceNinjaApe/advanced-express-api/tree/master/src/property-validator
Şerefe