0

Hope everyone of you are doing well. I am stuck in a bit of problem. Any help will be highly appreciated.

I am using ldapJS and I want to call another promise from searchEntry method of LDAPJS. When i write the code same as below. it throws an error

exports.getADUsers = async (reqst, resp, next) => {
    let flag = false;
    var finalList = [];
    let adConnStatus = await ConnectAD()
        .then().catch((errConnStatus) => {
            console.log("Error in connection with Active directory " + errConnStatus);
        });

    if (adConnStatus.status == 0) {
        let client = adConnStatus.client;
        const opts = {
            filter: '(ObjectClass=*)',
            scope: 'sub',
            attributes: ['cn', 'sid', "objectSid"]
        };
        client.search('dc=domain,dc=com', opts, (err, res) => {
            if (err) {
                console.log("Error: " + err);
            } else {
                res.on('searchEntry', (entry) => {
                    finalList = await searchEntry(entry);
                });
                res.on('searchReference', (referral) => {
                    console.log('referral: ' + referral.uris.join());
                });
                res.on('error', (err) => {
                    console.error('error: ' + err.message);
                });
                res.on('end', (result) => {
                    resp.send(finalList);
                    console.log(result);
                });
            }
        });
    }
}

Error:

finalList = await searchEntry(entry);
            ^^^^^

SyntaxError: await is only valid in async function

Please help! how to call another promise from one promise. Though the method is async why it shows this message? what am i doing wrong?

EDIT

After adding the keyword async as suggested by @Punth. Also modifying a bit of the code. my new code is as follows.

exports.getADUsers = async (reqst, resp, next) => {
    let adConnStatus = await ConnectAD()
        .then().catch((errConnStatus) => {
            console.log("Error in connection with Active directory " + errConnStatus);
        });

    if (adConnStatus.status == 0) {
        var adUsersList = [];
        let client = adConnStatus.client;
        const opts = {
            filter: '(ObjectClass=*)',
            scope: 'sub',
            attributes: ['cn', 'sid', "objectSid"]
        };
        client.search('dc=domain,dc=com', opts, (err, res) => {
            if (err) {
                console.log("Error: " + err);
            } else {
                res.on('searchEntry', async (entry) => {
                    var raw = entry.raw;
                    if (raw.objectSid != "undefined" && raw.objectSid != null && entry.object.cn != null && entry.object.cn != "undefined") {
                        let userData = {
                            "Name": entry.object.cn,
                            "SSID": sidBufferToString(raw.objectSid)
                        }
                        var lmn = await ConnectAndGetUsersList(userData.SSID);
                        userData["XYZ"] = lmn.xyz;
                        userData["ABC"] = lmn.abc;
                        adUsersList.push(userData);
                    }
                });
                res.on('searchReference', (referral) => {
                    console.log('referral: ' + referral.uris.join());
                });
                res.on('error',  (err) => {
                    console.error('error: ' + err.message);
                });
                res.on('end', (result) => {
                    console.log(result);
                    resp.send(adUsersList);
                });
            }
        });
    }
}

By running the above code it doesn't shows me anything. res.on('end' ....) is called prior to res.on("searchEntry"....) Therefore the array of adUsersList is null.

Now my question is how to resp.send the final arraylist???

Asad Mehmood
  • 292
  • 2
  • 10
  • 20
  • 2
    `(err, res) => {…}` and `(entry) => { … }` are **not** `async` methods – Bergi Jun 28 '21 at 12:05
  • How many `searchEntry` events do you expect from the response stream? – Bergi Jun 28 '21 at 12:08
  • Yep, your `client.search` is not an async method so you can't use await inside. just do `searchEntry(entry).then(...)` – AdityaParab Jun 28 '21 at 12:08
  • @Bergi Search entry events may differ from 100s to millions – Asad Mehmood Jun 28 '21 at 12:16
  • @Bergi then how to make it work smoothly? What is the proposed solution? – Asad Mehmood Jun 28 '21 at 12:16
  • @AdityaParab that won't show any positivity cause the promise state is still pending. using then() won't impact. – Asad Mehmood Jun 28 '21 at 12:17
  • @AsadMehmood If there are so many events, `finalList = await searchEntry(entry);` and `resp.send(finalList);` doesn't make sense - `finalList` is meant to be a list (an array)? – Bergi Jun 28 '21 at 12:18
  • @Bergi thats what I am asking, how to return the fulfilled promise? – Asad Mehmood Jun 28 '21 at 12:20
  • @AsadMehmood But that's the wrong question: there isn't just one fulfilled promise, there are many – Bergi Jun 28 '21 at 12:20
  • 1
    @Bergi can you please help in how to overcome this issue of await is only valid in async method. oh! wait let me update my question i forgot to add search entry method part – Asad Mehmood Jun 28 '21 at 12:24
  • I would probably suggest something like `res.on('searchEntry', entry => { promiseList.push(searchEntry(entry)); });` with `res.on('end', result => { console.log(result); Promise.all(promiseList).then(finalList => resp.send(finalList)); });`. However, depending on what `searchEntry` does, you might need to account for backpressure and error handling. – Bergi Jun 28 '21 at 13:25

1 Answers1

-1

Update this line as follows, to invoke promises using async/await syntax inside a callback you need to make it async

 res.on('searchEntry', async (entry) => {
   finalList = await searchEntry(entry);
 });
Punith K
  • 656
  • 1
  • 9
  • 26
  • Please add a comment explaining why the answer was downvoted. It would be useful for me and the community. I'm open to know and learn the missing pieces. – Punith K Jun 28 '21 at 12:28
  • @PunithK Look at how the `finalList` variable is used and you'll realise that this code won't actually work – Bergi Jun 28 '21 at 12:44
  • @Bergi yes, you are right, I didn't look into the whole code and I was trying to solve the error that he was pointed at. I read your comments, I agree. – Punith K Jun 28 '21 at 15:53
  • @PunithK Thanks you! that solved my issue but there is another problem `res.on('end', () => { // some code})` is called prior to `searchEntry`. I tried to put `async` but did not worked! Do you have any idea as how to solve it? – Asad Mehmood Jun 29 '21 at 05:14
  • @AsadMehmood You must have a clear mental model on how the event loop works in NodeJS. Event `end` is fired synchronously while you are still performing the async action on `SearchEntry`. One probable solution would be to broadcast the `end` event when you are done resolving all the promises inside `searchEntry`. Otherwise, you can follow the solution @Bergi offered above using `Promise.all()` – Punith K Jun 29 '21 at 06:18