Javascript Angular2将服务方法从回调更改为异步
我启动了一个简单的Angular2 Electron应用程序,我有一个查询本地SQL Server数据库的服务方法。到目前为止一切正常。现在,我正在尝试获取对我的组件的service DB调用的结果,并以某种方式显示它 问题在于,查询逻辑更多地是针对回调语法编写的:Javascript Angular2将服务方法从回调更改为异步,javascript,angular,asynchronous,angular-promise,Javascript,Angular,Asynchronous,Angular Promise,我启动了一个简单的Angular2 Electron应用程序,我有一个查询本地SQL Server数据库的服务方法。到目前为止一切正常。现在,我正在尝试获取对我的组件的service DB调用的结果,并以某种方式显示它 问题在于,查询逻辑更多地是针对回调语法编写的: sql.query(sqlString, (err, result) => { ... callback(result); ... }); 我很难重写它以返回一个承诺,因为结果总是在query命令函数
sql.query(sqlString, (err, result) => {
...
callback(result);
...
});
我很难重写它以返回一个承诺,因为结果总是在query命令函数的result参数内。我的组件如下所示:
export class LinkDocRetriever {
constructor(private myService: MyService) { }
results = "";
loadMyData(id: number): void {
let tcData = this.myService.getMyData();
tcData.forEach(element => {
this.results += element.FileName + " " + "....\n";
});
};
}
我的服务是这样的:
import { Injectable } from "@angular/core";
import * as sql from "mssql";
@Injectable()
export class MyService {
getMyData():Array<MyItem> {
let myData:Array<MyItem> = [];
let config = {
user: "sa",
password: "xxx",
server: "localhost",
database: "mydb"
};
const pool1 = new sql.ConnectionPool(config, err => {
if (err) {
console.log("connect erro: " + err);
}
let q:string = `SELECT TOP 10 * FROM MyTable;`;
let final = pool1.request()
.query<MyItem>(q, (err, result) => {
if (err) {
console.log("request err: " + err);
}
console.log("db result count: " + result.recordsets[0].length);
result.recordsets[0].forEach(row => {
myData.push(row);
});
});
});
return myData;
}
}
从“@angular/core”导入{Injectable};
将*作为sql从“mssql”导入;
@可注射()
导出类MyService{
getMyData():数组{
让myData:Array=[];
让配置={
用户:“sa”,
密码:“xxx”,
服务器:“本地主机”,
数据库:“mydb”
};
constpool1=newsql.ConnectionPool(配置,错误=>{
如果(错误){
日志(“连接错误:+err”);
}
让q:string=`从MyTable中选择前10个*;
让final=pool1.request()
.查询(q,(错误,结果)=>{
如果(错误){
log(“请求错误:+err”);
}
console.log(“数据库结果计数:+result.recordset[0].length”);
result.recordset[0]。forEach(行=>{
myData.push(行);
});
});
});
返回myData;
}
}
我确实返回了一个结果,但组件从未看到它,因为它在返回结果之前返回
我已经尝试在ConnectionPool函数中对查询调用进行wait,但是我得到一个错误,指出只能在异步函数中调用wait,即使我在该方法上设置了async。mssql包有一个,但当我尝试它时,该页上给定的语法会出错
你知道我如何使用promise编写这篇文章吗?正如你所指出的,处理异步函数有三种方法:使用回调、使用promise和使用async/Await。我将尝试展示这三种方式,但您应该了解javascript中的事件循环以及它如何处理异步函数 回调 回调在技术上是处理异步函数的最快方法,但一开始它很混乱,如果使用不当,可能会创建一个称为回调地狱的东西。回调地狱非常可怕,甚至有人为此创建了一个网站 因此,您可以将代码重写为:
export class LinkDocRetriever {
constructor(private myService: MyService) { }
results = "";
loadMyData(id: number): void {
// call getMyData with a function as argument. Typically, the function takes error as the first argument
this.myService.getMyData(function (error, tcData) {
if (error) {
// Do something
}
tcData.forEach(element => {
this.results += element.FileName + " " + "....\n";
});
});
};
}
服务
import { Injectable } from "@angular/core";
import * as sql from "mssql";
@Injectable()
export class MyService {
// Now getMyData takes a callback as an argument and returns nothing
getMyData(cb) {
let myData = [];
let config = {
user: "sa",
password: "xxx",
server: "localhost",
database: "mydb"
};
const pool1 = new sql.ConnectionPool(function(config, err) {
if (err) {
// Error occured, evoke callback
return cb(error);
}
let q:string = `SELECT TOP 10 * FROM MyTable;`;
let final = pool1.request()
.query<MyItem>(q, (err, result) => {
if (err) {
console.log("request err: " + err);
// Error occured, evoke callback
return cb(error);
}
console.log("db result count: " + result.recordsets[0].length);
result.recordsets[0].forEach(row => {
myData.push(row);
});
// Call the callback, no error occured no undefined comes first, then myData
cb(undefined, myData);
});
});
}
}
@Injectable()
export class MyService {
// Now getMyData doesn't take any argument at all and return a Promise
getMyData() {
let myData = [];
let config = {
user: "sa",
password: "xxx",
server: "localhost",
database: "mydb"
};
// This is what getMyData returns
return new Promise(function (resolve, reject) {
const pool1 = new sql.ConnectionPool((config, err) => {
if (err) {
// If error occurs, reject Promise
reject(err)
}
let q = `SELECT TOP 10 * FROM MyTable;`;
let final = pool1.request()
.query(q, (err, result) => {
if (err) {
// If error occurs, reject Promise
reject(err)
}
console.log("db result count: " + result.recordsets[0].length);
result.recordsets[0].forEach((row) => {
myData.push(row);
});
//
resolve(myData);
});
});
})
}
}
服务
import { Injectable } from "@angular/core";
import * as sql from "mssql";
@Injectable()
export class MyService {
// Now getMyData takes a callback as an argument and returns nothing
getMyData(cb) {
let myData = [];
let config = {
user: "sa",
password: "xxx",
server: "localhost",
database: "mydb"
};
const pool1 = new sql.ConnectionPool(function(config, err) {
if (err) {
// Error occured, evoke callback
return cb(error);
}
let q:string = `SELECT TOP 10 * FROM MyTable;`;
let final = pool1.request()
.query<MyItem>(q, (err, result) => {
if (err) {
console.log("request err: " + err);
// Error occured, evoke callback
return cb(error);
}
console.log("db result count: " + result.recordsets[0].length);
result.recordsets[0].forEach(row => {
myData.push(row);
});
// Call the callback, no error occured no undefined comes first, then myData
cb(undefined, myData);
});
});
}
}
@Injectable()
export class MyService {
// Now getMyData doesn't take any argument at all and return a Promise
getMyData() {
let myData = [];
let config = {
user: "sa",
password: "xxx",
server: "localhost",
database: "mydb"
};
// This is what getMyData returns
return new Promise(function (resolve, reject) {
const pool1 = new sql.ConnectionPool((config, err) => {
if (err) {
// If error occurs, reject Promise
reject(err)
}
let q = `SELECT TOP 10 * FROM MyTable;`;
let final = pool1.request()
.query(q, (err, result) => {
if (err) {
// If error occurs, reject Promise
reject(err)
}
console.log("db result count: " + result.recordsets[0].length);
result.recordsets[0].forEach((row) => {
myData.push(row);
});
//
resolve(myData);
});
});
})
}
}
异步/等待
Async/await的引入是为了解决您在处理回调和承诺时遇到的困惑。阅读有关异步/等待的更多信息
组成部分
export class LinkDocRetriever {
constructor(private myService: MyService) { }
results = "";
loadMyData(id: number): void {
this.myService.getMyData()
.then((tcData) => {
// Promise uses then function to control flow
tcData.forEach((element) => {
this.results += element.FileName + " " + "....\n";
});
})
.catch((error) => {
// Handle error here
});
};
}
export class LinkDocRetriever {
constructor(private myService: MyService) { }
results = "";
// Look. loadMyData now has to have async keyword before to use await. Beware, now loadMyData will return a Promise.
async loadMyData(id) {
// By using await, syntax will look very familiar now
let tcData = await this.myService.getMyData(tcData);
tcData.forEach((element) => {
this.results += element.FileName + " " + "....\n";
});
};
}
服务将与Promise中的服务完全相同,因为Async/await是专门为处理它们而创建的
注意:我从您的代码中删除了一些Typescript功能,因为我更习惯vanilla JS,但您应该能够编译它们,因为Typescript是JS的超集。我认为我的问题是试图以“旧”的方式执行,返回一个promise.defer(),然后设置拒绝和解决。这种新方法将整个承诺定义包装在异步代码周围+1的额外解释和清晰度。