简体   繁体   English

为什么我的异步 function 不等待 promise 完成

[英]Why isn't my async function waiting for the promise to be fulfilled

I am using ldapjs to query users from an ldap server.我正在使用 ldapjs 从 ldap 服务器查询用户。 If I put all the code just in a single script without using functions, the query works and I get the results I need.如果我将所有代码只放在一个脚本中而不使用函数,则查询有效并且我得到我需要的结果。

I am now trying to use expressjs to serve a rest endpoint to enable querying of the ldap server, so I moved the ldapjs client.search code into a async function with a promise surrounding the actual search code. I am now trying to use expressjs to serve a rest endpoint to enable querying of the ldap server, so I moved the ldapjs client.search code into a async function with a promise surrounding the actual search code. After the promise code, I have a line which exercises the promise using await and stores the results of the promise in a variable.在 promise 代码之后,我有一行使用 await 练习 promise 并将 promise 的结果存储在变量中。 I then return that variable to the calling function which will eventually send the results back as a json-formatted string to the requesting browser.然后我将该变量返回给调用 function 最终将结果作为 json 格式的字符串发送回请求浏览器。

The problem I am seeing is that the console.log() of the returned results is undefined and appears before the console.log statements inside the promise code.我看到的问题是返回结果的 console.log() 是未定义的,并且出现在 promise 代码中的 console.log 语句之前。 So it looks like the async function is returning before the promise is fulfilled, but I don't see why because in all the examples of promises and async/await I have seen this scenario works correctly.所以看起来异步 function 在 promise 完成之前返回,但我不明白为什么,因为在所有的 promises 和 async/await 示例中,我已经看到这种情况正常工作。

Below is a sample script without the expressjs part to just make sure everything works correctly.下面是一个没有 expressjs 部分的示例脚本,以确保一切正常。

// script constants:
const ldap = require('ldapjs');
const assert = require('assert');
const ldapServer = "ldap.example.com";
const adSuffix = "dc=example,dc=com"; // test.com
const client = getClient();

const fullName = "*doe*";

var opts = {
  scope: "sub",
  filter: `(cn=${fullName})`,
  attributes: ["displayName", "mail", "title", "manager"]
};
console.log("performing the search");
let ldapUsers = doSearch(client, opts);
console.log("Final Results: " + ldapUsers);

function getClient() {
  // Setup the connection to the ldap server
  ...
  return client;
}

async function doSearch(client, searchOptions) {
  console.log("Inside doSearch()");
  let promise = new Promise((resolve, reject) => {
    users = '{"users": [';
    client.search(adSuffix, searchOptions, (err, res) => {
      if (err) {
        console.log(err);
        reject(err)
      }
      res.on('searchEntry', function(entry) {
        console.log("Entry: " + users.length);
        if (users.length > 11) {
          users = users + "," + JSON.stringify(entry.object);
        } else {
          users = users + JSON.stringify(entry.object);
        }
      });

      res.on('error', function(err) {
        console.error("Error: " + err.message);
        reject(err)
      });
      res.on('end', function(result) {
        console.log("end:");
        client.unbind();
        users = users + "]}";
        resolve(users)
      });
    });
  });


  // resolve the promise:
  let result = await promise;
  console.log("After promise has resolved.");
  console.log(result);
  return result
}

The output from the console.log statements is as follows: console.log 语句中的 output 如下:

Setting up the ldap client.
ldap.createClient succeeded.
performing the search
Inside doSearch()
Final Results: [object Promise]
Entry: 11
end:
After promise has resolved.
{"users": [{"dn":"cn=john_doe"}]}

I did strip out the code which creates the ldapjs client and redacted the company name, but otherwise this is my code.我确实删除了创建 ldapjs 客户端的代码并编辑了公司名称,否则这是我的代码。

Any ideas on why the doSearch function is returning before the promise is fulfilled would be greatly appreciated.关于为什么 doSearch function 在 promise 完成之前返回的任何想法将不胜感激。

As @danh mentioned in a comment, you're not await ing the response from doSearch .正如@danh 在评论中提到的那样,您不会await来自doSearch的响应。 Since doSearch is an async function it will always return a promise, and thus must be await ed.由于doSearch是一个async function 它总是会返回一个 promise,因此必须await ed。

As a quick and dirty way to do that you could wrap your call in an immediately invoked asynchronous function like so:作为一种快速而肮脏的方法,您可以将调用包装在立即调用的异步 function 中,如下所示:

// ...

(async () => console.log(await doSearch(client, opts)))();

// ...

For more info you might check out the MDN docs on asynchronous functions有关更多信息,您可以查看有关异步函数的 MDN 文档

I think there are a few issues in the provided code snippet.我认为提供的代码片段中存在一些问题。 As @danh pointed out you need to await the doSearch call.正如@danh 指出的那样,您需要await doSearch调用。 However you may have not done that already since you may not be using an environment with a top async .但是,您可能还没有这样做,因为您可能没有使用带有顶级async的环境。 This likely means you'll want to wrap the call to doSearch in an async function and call that.这可能意味着您需要将对doSearch的调用包装在异步 function 中并调用它。 Assuming you need to await for the search results.假设您需要等待搜索结果。

// script constants:
const ldap = require('ldapjs');
const assert = require('assert');
const ldapServer = "ldap.example.com";
const adSuffix = "dc=example,dc=com"; // test.com
const client = getClient();

const fullName = "*doe*";

function getClient() {
  // Setup the connection to the ldap server
  ...
  return client;
}

async function doSearch(client, searchOptions) {
  console.log("Inside doSearch()");
  return new Promise((resolve, reject) => {
    users = '{"users": [';
    client.search(adSuffix, searchOptions, (err, res) => {
      if (err) {
        console.log(err);
        reject(err)
      }
      res.on('searchEntry', function(entry) {
        console.log("Entry: " + users.length);
        if (users.length > 11) {
          users = users + "," + JSON.stringify(entry.object);
        } else {
          users = users + JSON.stringify(entry.object);
        }
      });

      res.on('error', function(err) {
        console.error("Error: " + err.message);
        reject(err)
      });
      res.on('end', function(result) {
        console.log("end:");
        client.unbind();
        users = users + "]}";
        console.log(result);
        resolve(users)
      });
    });
  });
}

const opts = {
  scope: "sub",
  filter: `(cn=${fullName})`,
  attributes: ["displayName", "mail", "title", "manager"]
};

(async function runAsyncSearch () {
  console.log("performing the search");
  try {
    const ldapUsers = await doSearch(client, opts); // Await the async results
    console.log("After promise has resolved.");
    console.log("Final Results: " + ldapUsers);
  } catch (err) {
    console.error(err.message);
  } 
})();  // Execute the function immediately after defining it.

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

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