简体   繁体   English

使用node.js作为后端来路由角度组件的最佳方法是什么

[英]What is the best way to do routing of angular components using node.js as backend

I am trying to to navigate through angular components (signup and dashboard). 我试图浏览角度组件(注册和仪表板)。 If the user has already signed up then he should be redirected to the dashboard component and if not then to signup component. 如果用户已经注册,则应将其重定向到仪表板组件,如果没有,则重定向到注册组件。 Running only lib.js file as the server. 仅运行lib.js文件作为服务器。 The angular files are deployed after using ng build command (making use of dist folder). 使用ng build命令(使用dist文件夹)后部署角度文件。 Both the front-end and back-end are in the same folder 前端和后端都在同一个文件夹中

Here are the some code snippets: 以下是一些代码片段:

lib.js (node.js back-end file) lib.js(node.js后端文件)

app.use(exp.static(path.join(__dirname, 'dist')));

app.listen(PORT, function() {
    console.log('Express server listening on port ', PORT); // eslint-disable-line
});

app.post('/check_account',function(req,res){
    console.log(req.body);
    connection.query('SELECT * FROM login_table WHERE m_pub_key LIKE '+'\"'+req.body.m_pub_key+'\"' ,function(error,rows,fields){
        if(!!error){
            console.log('error!');
            res.send('Error!');
        }
        else
            {
                console.log(rows);
                if(rows.length!=0){
                    data={
                        is_signed_up: 1
                    }
                    res.send(data);
                }
                else{
                    data={
                        is_signed_up: 0
                    }
                    res.send(data);
                }
            }
    });

});

app.get('/dashboard',function(req,res){
    console.log("inside dashboard backend");
    res.sendFile(path.join(__dirname, 'dist/index.html'));
});

app.get('/signup', function (req,res) {
    console.log("signup backend");
    res.sendFile(path.join(__dirname, 'dist/index.html'));
});

app.get('/', function (req,res) {
    console.log("slash backend");
    res.sendFile(path.join(__dirname, 'dist/index.html'));
});

app.component.ts app.component.ts

  constructor(private router: Router,private _appService: AppService, private zone: NgZone, private http: HttpClient, private route: ActivatedRoute){
    console.log("inside app component constructor");
    this.checkAndInstantiateWeb3();
    this.onReady();

  }

  checkAccount(){
    let data_send = JSON.stringify({
            'm_pub_key': this.m_pub_key
        });

      this.zone.runOutsideAngular(()=>{
        this._appService.post_method(this.url+"check_account", data_send).subscribe(
          data => {
              this.is_signed_up=data["is_signed_up"];
              console.log(this.is_signed_up+"***************8");
              if(this.is_signed_up==1){
                console.log("navigating to dash");
                this.router.navigate(['/dashboard']);
                //this.http.get("/dashboard");
              }
              else{
                console.log("navigating to signuo");
                this.router.navigate(['/signup']);
                //this.http.get("/signup");
              }
          },
          error => {
              // console.log('post error');
          });
});
  }

  public checkAndInstantiateWeb3 = () => {
        if (typeof window.web3 !== 'undefined') {
            console.warn('Using injected web3');
            this.web3 = new Web3(window.web3.currentProvider);
        } else {
            // when running in browser, use incognito mode or log out of metamask
            console.warn('No web 3 detected, falling back to Ganache');
            this.provider = new Web3.providers.HttpProvider('http://localhost:7545');
            this.web3 = new Web3(this.provider);
        }
        window.ethereum.enable();
      }

  public onReady = () => {
        // get initial account balance so it can be displayed
        this.web3.eth.getAccounts((err, accs) => {
          if (err != null) {
            console.log(err);
            alert('There was an error fetching your accounts.');
            return;
          }

          if (accs.length === 0) {
            alert('You are not connected to an Ethereum client.');
            return;
          }
          this.m_pub_key=accs[0];
          console.log(this.m_pub_key);
          this.checkAccount();
        });
      }
}

app-routing.module.ts APP-routing.module.ts

const routes: Routes = [
    { path: 'signup', component: SignupComponent },
    { path: '', pathMatch: 'full', redirectTo: 'signup' },
    { path: 'dashboard', component: DashboardComponent },
];

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule],
})
export class AppRoutingModule { }

Now the problem is that if the user has already signed up and then when he tries to go to any page he is redirected to 1st the signup page and then dashboard page but both the pages overlap and also the dashboard component does not work properly. 现在的问题是,如果用户已经注册,然后当他尝试转到任何页面时,他将被重定向到第一个注册页面,然后重定向到仪表板页面,但两个页面重叠,仪表板组件也无法正常工作。 When user directly goes to the dashboard component using the url then the dashboard component works as expected. 当用户使用URL直接转到仪表板组件时,仪表板组件将按预期工作。 Any help in this problem would be appreciated. 任何有关这个问题的帮助将不胜感激。

EDIT 1 编辑1

Following the answer given by "k0hamed". 按照“k0hamed”给出的答案。 Using the canActivate attriute like this { path: 'signup', component: SignupComponent, canActivate:[AuthGuard] } This are the guard and service files i have created and its not working as expected. 像这样使用canActivate attriute { path: 'signup', component: SignupComponent, canActivate:[AuthGuard] }这是我创建的防护和服务文件,它不能按预期工作。 The val in the auth.guard.ts file does not change and nothing gets loaded when i go to localhost:8080/ or localhost:8080/signup but the dashboard component loads when i type in localhost:8080/dashboard 当我转到localhost:8080 /或localhost:8080 / signup时,auth.guard.ts文件中的val不会更改并且没有任何内容被加载,但当我输入localhost时,仪表板组件会加载:8080 / dashboard

auth.guard.ts: auth.guard.ts:

export class AuthGuard implements CanActivate {
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
    ): Observable<boolean> {
    console.log('AuthGuard#canActivate called');
    return this.signupService.onReady()
             .pipe(tap(val=>!val && this.router.navigate(['/signup'])));
  }
  constructor(private signupService: AuthService, private router: Router) {}
}

auth.service.ts: auth.service.ts:

export class AuthService {

    provider: any;
    account: any;
    accounts: any;
    web3: any;
    m_pub_key="";
    title = 'project2';
    is_signed_up:any;
    url = "http://localhost:8080/";
    val = of(false);

    constructor(private _appService: AppService, private zone: NgZone, private router: Router){
    }

    onReady():Observable<boolean> {
        // get initial account balance so it can be displayed
        // (async () => {
        if (typeof window.web3 !== 'undefined') {
            console.warn('Using injected web3');
            this.web3 = new Web3(window.web3.currentProvider);
        } else {
            // when running in browser, use incognito mode or log out of metamask
            console.warn('No web 3 detected, falling back to Ganache');
            this.provider = new Web3.providers.HttpProvider('http://localhost:7545');
            this.web3 = new Web3(this.provider);
        }
        window.ethereum.enable();


        this.web3.eth.getAccounts((err, accs) => {
          if (err != null) {
            console.log(err);
            alert('There was an error fetching your accounts.');
            return;
          }

          if (accs.length === 0) {
            alert('You are not connected to an Ethereum client.');
            return;
          }
          this.m_pub_key=accs[0];
          console.log(this.m_pub_key);
          // this.isSigned();
        });

        let data_send = JSON.stringify({
            'm_pub_key': this.m_pub_key
        });
            this._appService.post_method(this.url+"check_account", data_send).subscribe(
              data => {
                  this.is_signed_up=data["is_signed_up"];
                  console.log(this.is_signed_up+"***************8");
                  if(this.is_signed_up==1){
                    console.log("navigating to dash");
                    //this.router.navigate(['/dashboard']);
                    //this.http.get("/dashboard");
                    this.val = of(false);
                    // this.router.navigate(['/dashboard']);
                  }
                  else{
                    console.log("navigating to signup");
                    //this.router.navigate(['/signup']);
                    //this.http.get("/signup");
                    this.val = of(true);
                    // this.router.navigate(['/signup']);
                  }
                  console.log(this.val);
              },
                    // console.log(this.val);
              error => {
                  // console.log('post error');
              });
        // });
        console.log(this.val);
        return this.val
      }
}

first of 首先

your shouldn't handle literally every route in the back-end if angular does so 如果有角度的话,你不应该在后端的每条路线上按字面处理

app.get('/*', function(req,res) {
  res.sendFile(path.join( __dirname + '/dist/index.html'));
});

adding this as the last route in your express app will redirect every request not handled above it to angular and angular will use it's own router 添加此作为您的快递应用程序中的最后一个路由将重定向每个未处理它上面的请求角度和角度将使用它自己的路由器

second of, you need to use a canActive guard for your use case and move the checking function within it, if user is not signed it will redirect to signup page, else it will allow him to pass, something like: 第二,你需要为你的用例使用canActive防护并在其中移动检查功能,如果用户没有签名,它将重定向到signup页面,否则它将允许他通过,例如:

@Injectable({
  providedIn: 'root',
})
export class AuthGuard implements CanActivate {
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> {
    console.log('AuthGuard#canActivate called');
    return this.signupService.isSigned()
             .pipe(tap(val => !val && this.router.navigate(['/signup']))); // Navigate to signup when it returns false
  }
  constructor(private signupService: SignupService, private router: Router) {}
}

While SignupService is a service with method isSigned() that return an Observable<boolean> ; 虽然SignupService是一个带有方法isSigned()的服务,它返回一个Observable<boolean> ;

You might need to create another guard for the signup page route, to check if not signed and redirect to dashboard otherwise. 您可能需要为signup页面路由创建另一个防护,以检查是否未签名并以其他方式重定向到仪表板。

UPDATE: You need to either turn your whole code into promises or observables, to handle asynchronous functions as the guards accepts observable and promise 更新:您需要将整个代码转换为promises或observable,以处理异步函数,因为守卫接受可观察和承诺

So for example to use the observables way you need to turn getAcounts function to return observable instead of depending on callback, fortunately rxJs has a build-in function to do so it's bindNodeCallback you can simply do 所以例如使用observables方式你需要把getAcounts函数转换为observable而不是依赖回调,幸运的是rxJs有一个内置函数来做这个它的bindNodeCallback你可以简单地做

const getAccountsAsObservable = bindNodeCallback(
    callback => this.web3.eth.getAccounts(callback));

now you can use rxJs magic to chain the code through pipes and you need to handle error with a pipe also and make it return an observable of false. 现在你可以使用rxJs magic通过管道链接代码,你也需要用管道处理错误,并使它返回一个可观察的false。

and your service will be something like: 你的服务将是这样的:

onReady():Observable<boolean> {
  // ..
  const getAccountsAsObservable = Observable.bindNodeCallback(
    callback => this.web3.eth.getAccounts(callback));

  return getAccountsAsObservable()
    .pipe(
      switchMap(acc => {
        if (accs.length === 0) {
          alert('You are not connected to an Ethereum client.');
          // throw an error to skip to "cathError" pipe
          return throwError(new Error('You are not connected to an Ethereum client.'));
        }
        const m_pub_key=accs[0];
        console.log(this.m_pub_key);
        const data_send = JSON.stringify({
          'm_pub_key': m_pub_key
        });
        return of(data_send);
      }),
      switchMap(data_send => { 
        this._appService.post_method(this.url+"check_account", data_send)
      }),
      map(data => {
        this.is_signed_up=data["is_signed_up"];
        console.log(this.is_signed_up+"***************8");
        if(this.is_signed_up==1){
          console.log("navigating to dash");
          //this.router.navigate(['/dashboard']);
          //this.http.get("/dashboard");
          return false;
          // this.router.navigate(['/dashboard']);
        } else {
          console.log("navigating to signup");
          //this.router.navigate(['/signup']);
          //this.http.get("/signup");
          return true;
          // this.router.navigate(['/signup']);
        }
      }),
      catchError(err => {
        //handle error of getAccounts or post_method here
        console.log(err);
        alert('There was an error fetching your accounts.');
        return of(false);
      })
    )
}

you can turn the whole thing into promises and/or use async/await you can turn _appService.post_method to promise with .pipe(take(1)).toPromise 你可以将整个事情变成promises和/或使用async / await你可以将_appService.post_method转为使用.pipe(take(1)).toPromise承诺.pipe(take(1)).toPromise

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Node.js中创建参数化“组件”的最佳方法是什么? - What is the best way to create parametrized “components” in Node.js? 从 Angular 8 发布到 Node.JS 的最佳方式是什么 - What is the best way to post from Angular 8 to Node.JS 使用Express.js(node.js)进行动态路由的最佳方法 - Best way to do dynamic routing with Express.js (node.js) 使用Node.js对数据进行经典形式处理的最佳方法是什么? - What's the best way to do classical forms over data using Node.js? 最好的写法是什么? 节点.JS - What is the best way to write it? Node.JS 我在Windows上使用Node.js,express,Angular,Postgresql。 在服务器之间镜像和编码更新的最佳方法是什么? - I am using Node.js, express, Angular, Postgresql on Windows. What is the best way to mirror and code updates between servers? 在node.js中使用事件的最佳方法 - Best way using events in node.js 有没有一种方法可以使用Node.js路由覆盖Angular路由器-仅针对特定路径? - Is there a way to override Angular router using Node.js routing - Just for a specific path? 使用带有 Node.js 后端的 Angular 应用程序进行 Google 登录 - Google Sign-in using Angular app with a Node.js backend 使用express在node.js中渲染LESS.js样式表的最佳方法是什么? - What is the best way to render LESS.js stylesheets in node.js using express?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM