【问题标题】:Why isn't my async function waiting for the promise to be fulfilled为什么我的异步功能不等待承诺被履行
【发布时间】:2021-06-28 20:12:00
【问题描述】:

我正在使用 ldapjs 从 ldap 服务器查询用户。 如果我将所有代码只放在一个脚本中而不使用函数,则查询有效并且我得到我需要的结果。

我现在正在尝试使用 expressjs 提供一个休息端点以启用对 ldap 服务器的查询,因此我将 ldapjs client.search 代码移动到一个异步函数中,并承诺围绕实际搜索代码。 在 Promise 代码之后,我有一行使用 await 来执行 Promise,并将 Promise 的结果存储在一个变量中。然后我将该变量返回给调用函数,该函数最终会将结果作为 json 格式的字符串发送回请求浏览器。

我看到的问题是返回结果的console.log() 是未定义的,并且出现在promise 代码中的console.log 语句之前。所以看起来 async 函数在 promise 完成之前就返回了,但我不明白为什么,因为在所有 promises 和 async/await 的例子中我都看到这个场景正常工作。

下面是一个没有 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
}

console.log 语句的输出如下:

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

我确实删除了创建 ldapjs 客户端的代码并编辑了公司名称,但除此之外,这是我的代码。

任何关于为什么 doSearch 函数在承诺实现之前返回的想法将不胜感激。

【问题讨论】:

  • 到目前为止只是略读,但您肯定应该等待 doSearch()

标签: javascript node.js async-await promise


【解决方案1】:

正如@danh 在评论中提到的,您不是awaiting 来自doSearch 的回复。由于doSearchasync 函数,它总是 返回一个promise,因此必须是awaited。

作为一种快速而肮脏的方法,您可以将调用包装在立即调用的异步函数中,如下所示:

// ...

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

// ...

有关更多信息,您可以查看 MDN docs on asynchronous functions

【讨论】:

  • 像你展示的那样包装根本没有用。它不会在等待代码执行后生成代码,所以这看起来非常具有误导性。
【解决方案2】:

我认为提供的代码 sn-p 存在一些问题。正如@danh 指出的那样,您需要拨打await doSearch 电话。但是,您可能还没有这样做,因为您可能没有使用顶级 async 的环境。这可能意味着您需要将对 doSearch 的调用包装在异步函数中并调用它。假设您需要等待搜索结果。

// 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.

【讨论】:

    猜你喜欢
    • 2019-04-29
    • 2017-06-15
    • 1970-01-01
    • 2023-01-23
    • 2018-02-03
    • 2018-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多