使用node.js作为后端进行角度组件布线的最佳方法是什么

时间:2019-03-31 06:44:59

标签: node.js angular angular2-routing

我正在尝试浏览角度组件(注册和仪表板)。如果用户已经注册,则应将其重定向到仪表板组件,否则应重定向到注册组件。仅运行lib.js文件作为服务器。使用ng build命令(使用dist文件夹)后,将部署角度文件。前端和后端都在同一个文件夹中

以下是一些代码段:

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

  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

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 { }

现在的问题是,如果用户已经注册,然后当他尝试转到任何页面时,他将被重定向到第一个注册页面和仪表板页面,但是这两个页面重叠并且仪表板组件也无法正常工作正确地。当用户使用url直接转到仪表板组件时,仪表板组件将按预期工作。在此问题上的任何帮助将不胜感激。

编辑1

按照“ k0hamed”给出的答案。 使用{ path: 'signup', component: SignupComponent, canActivate:[AuthGuard] }这样的canActivate属性 这是我创建的保护文件和服务文件,其无法正常工作。 auth.guard.ts文件中的val不会更改,并且当我进入localhost:8080 /或localhost:8080 / signup时不会加载任何内容,但是当我输入localhost:8080 / dashboard <时仪表板组件会加载< / p>

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:

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
      }
}

1 个答案:

答案 0 :(得分:0)

如果angular这样做,那么您不应真正处理后端的每条路线

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

将其添加为快速应用程序中的最后一条路由会将所有在其上方未处理的请求重定向到angular和angular will use it's own router

第二秒,您需要在使用案例中使用canActive guard 并在其中移动检查功能,如果用户未签名,它将重定向到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) {}
}

SignupService是具有方法isSigned()的服务,该服务返回Observable<boolean>;

您可能需要为signup页面路由创建另一个防护,以检查是否未签名,否则重定向到仪表板。

更新: 您需要将整个代码转换为Promise或Observable,以在Guard接受Observable和Promise时处理异步函数

因此例如使用可观察的方式 您需要打开getAcounts函数以返回可观察的值,而不是依赖于回调,幸运的是rxJs具有内置函数,它是bindNodeCallback 您只需完成

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

现在您可以使用rxJs magic通过管道链接代码 并且您还需要使用pipe处理错误,并使其返回可观察到的false。

您的服务将类似于:

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);
      })
    )
}

您可以将整个事情变成承诺和/或使用异步/等待 您可以通过.pipe(take(1)).toPromise

来使_appService.post_method做出承诺
相关问题