You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在非async函数中等待Promise?(基于node-mssql)

解决Node.js中MS SQL库阻塞式执行的需求

核心问题

现有项目依赖阻塞式的数据库操作逻辑,但node-mssql返回Promise(异步非阻塞),无法直接适配现有代码;重构整个项目的成本过高,需要找到能让代码等待Promise完成后再返回结果的方案,或者更换支持阻塞执行的MS SQL库。

方案一:用工具将异步Promise转为同步(应急方案)

Node.js本身是异步非阻塞设计,强行同步会破坏其并发特性,但可通过deasync工具实现“伪同步”,仅适合脚本类低并发场景,不推荐生产服务端使用。

示例代码

先安装依赖:

npm install deasync

修改原有类实现:

// 模拟node-mssql的connect方法
const sql = {
  connect: (config) => new Promise(resolve => {
    setTimeout(() => resolve({query: (sqlStr) => sqlStr}), 2000)
  })
}
const deasync = require('deasync');

class Foo {
  db;

  constructor() {
    this.db_connect();
  }

  db_connect() {
    let done = false;
    let connection;
    // 发起异步连接,用标记等待完成
    sql.connect().then(conn => {
      connection = conn;
      done = true;
    }).catch(err => {
      done = true;
      throw err;
    });
    // 轮询事件循环直到连接完成
    while (!done) {
      deasync.runLoopOnce();
    }
    this.db = connection;
  }

  db_query(sqlStr) {
    let done = false;
    let result;
    // 发起异步查询,等待结果
    this.db.query(sqlStr).then(res => {
      result = res;
      done = true;
    }).catch(err => {
      done = true;
      throw err;
    });
    while (!done) {
      deasync.runLoopOnce();
    }
    return result;
  }
}

const foo = new Foo();
console.log(foo.db_query(`SELECT * FROM bar WHERE spam='eggs'`));

方案二:更换支持同步执行的MS SQL库

直接使用原生支持阻塞式调用的库,比如mssql-sync,无需修改原有代码的阻塞逻辑结构。

示例代码

先安装依赖:

npm install mssql-sync

适配原有类:

const sql = require('mssql-sync');

class Foo {
  db;

  constructor() {
    this.db_connect();
  }

  db_connect() {
    // 同步建立连接,直到完成才返回
    this.db = sql.connect({
      server: '你的数据库地址',
      database: '目标数据库',
      user: '用户名',
      password: '密码'
    });
  }

  db_query(sqlStr) {
    // 同步执行查询,直接返回结果
    return sql.query(sqlStr);
  }
}

const foo = new Foo();
console.log(foo.db_query(`SELECT * FROM bar WHERE spam='eggs'`));

为什么非async函数里实现await效果这么难?

Node.js基于事件循环实现异步非阻塞,await是Promise的语法糖,依赖async函数的执行上下文来暂停函数、等待Promise完成。非async函数没有这个上下文,无法原生支持暂停执行——强行模拟只能通过轮询事件循环的hack方式,这不仅繁琐,还会阻塞整个事件循环,影响并发能力,因此官方并不推荐这种用法。

内容的提问来源于stack exchange,提问作者droptix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 12:01:24