简体   繁体   中英

How to handle Promise in nodejs

I'm trying to execute a callback function in nodejs, using expressjs and angular 2 (i don't know if the angular2 part it's relevant).

What I do is: I have a formular in angular2, with that I send a get request to my API route, then I send the text field in the formular to the URL via get, then I do an MYSQL query to look into a phonebook database, and I'm expecting to get a complete user with his details, from the phonebook.

Formular:

<div class="container">
<div class="col-md-4">
<h1>Addressbook</h1>
<form [formGroup]="searchForm" (ngSubmit)="doSearch($event)">
<input formControlName="searchString" type="text" placeholder="Name">
<button type="submit">Search</button>
</form>
</div>
</div>

First function, doSearch:

doSearch(event) {
    let formData = this.searchForm.value;
    var searchString = this.searchForm.value.searchString;

    this.http.get('/phonebook/search/'+searchString, function(req, res){}).subscribe(
    function(response) {
    console.log("Success Response");
    },
    function(error) { console.log("Error happened" + error)},
    function() { console.log("the subscription is completed")}
    );
}

This calls to the route sending a parameter, so not so hard.

Now the create router gets into the game:

public static create(router: Router, basePath: string) {
    console.log("[SearchRoute::create] Creating routes for /search.");
    // call the function for retrieving the address book results
    router.get(basePath + "/search/:searchString", (req: Request, res: Response, next: NextFunction) => {
    console.log("##  [SearchRoute] Called GET /search.");
    var object = searchUser(req);
    console.log(object);
        });
}

And finally, the function searchUser gets called:

function searchUser(req: Request) {

    console.log("searchUser Function executed.");

    var searchString = req.params.searchString;

    var query = p_query('SELECT XXXX')
    .then(function (results) {
    console.log("query executed and all okay");
    return (results);
    })
    .catch(function (error) {
    console.error("Wooopsi", error);
    });

    console.log("query result: "+query);
}

Additionally, I post here the new query function that I build to be able to handle promises (which I don't know if it was the best choice):

function p_query(q) {
    return new Promise(function (resolve, reject) {
    // The Promise constructor should catch any errors thrown on
    // this tick. Alternately, try/catch and reject(err) on catch.
    myMYSQL.db.query(
    q,
    function (error, results) {
    if (error)
    reject(error);
    resolve(results);
    });
    })
};

So, what I actually want to do, what's my issue?

I want to send the result of the query back to the client (the angular2 formular), and I was not being able to do it...

So after this really long post, I really appreciate if you read til here, and sorry for the complicated question!

PS: I know i explain myself really bad :(

Regards, Daniel

You should go with recursive callback with each query results try to enjoy the beauty of async platform. Send data to client via

res.send(data);

In this official angular 2 documentation on the http client they propose to put the http logic into a separate service. I've setup it similar to the example just for a search.service.ts:

import { Injectable } from '@angular/core';
import { Http, Response,Headers, RequestOptions,URLSearchParams }
          from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

@Injectable()
export class SearchService {
    constructor(private http: Http) { 
    }

    getSearchResult(searchString)  : Observable<any>  {
        return this.http.get('/phonebook/search/'+searchString)
         .map(this.extractData)
         .catch(this.handleError);
    }

    private extractData(res: Response) {
        let body = res.json();
        return body;
    }
    private handleError (error: Response | any) {
        let errMsg: string;
        if (error instanceof Response) {
            const body = error.json() || '';
            const err = body.error || JSON.stringify(body);
            errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
        } else {
            errMsg = error.message ? error.message : error.toString();
        }
        return Observable.throw(errMsg);
    }
}

In your component import the service and do the code snippets:

// don't forget to put the service in the app.modul or the component providers!
  constructur(public mySearchService : SearchService) {}

// in your doSearch of your component:
   doSearch(event) {
    let formData = this.searchForm.value;
    var searchString = this.searchForm.value.searchString;
    mySearchService.getSearchResult(searchString).subscribe(
        data => mylist.data, // or which datastructure I want to write to.
        error => console.error(error) // or how I log the errors..
    );
   }

EDIT: The search_user in your database model:

function searchUser(searchString) {
   console.log("searchUser Function executed.");
   return myMYSQL.db.select('phonebookentry', {
        pbe_lastname: searchString, pbe_syncstate: 'new'
   }) // returning the promise/observable to the main function...
} // Currently I don't know, how the returned data looks like.

On the node/express side in the router send it with res.json EDIT: use asynchronous call to searchUser :

router.get(basePath + "/search/:searchString", 
    (req: Request, res: Response, next: NextFunction) => {
    console.log("##  [SearchRoute] Called GET /search.");
    searchUser(req)
     .then( data => res.json(data);console.log(data) )
     .catch (error => console.log(error));
    });

Your answer it's completely perfect, i understand everything! The only problem that i'm facing now, its this one:

I'm calling the function searchUser, and it doesn't return anything, just an undefined object, so i quess i'm not doing the return correctly.

That's my searchUser function:

function searchUser(searchString) {

console.log("searchUser Function executed.");

myMYSQL.db.select('phonebookentry', {
pbe_lastname: searchString,
pbe_syncstate: 'new'
}).then(function (user) {
console.log("user before: "+user);
return (user);
}).catch(function (err) {
console.log(err);
})}

Thank you so much for your useful answer! I'm almost finished here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM