【问题标题】:How to convert Asynchronous to Synchronous in node js如何在节点js中将异步转换为同步
【发布时间】:2020-07-16 17:54:34
【问题描述】:

我是nodejs的菜鸟,现在遇到了一个nodejs异步和同步的问题。

这是我的代码:

var time_begin = Date.now();
console.log("begin time:" + time_begin);

arr_a = ['a', 'b', 'a', 'b', 'a', 'b']

async function iterTrans (arr_a) {

    var txs_arr_tmp = [];
    for(let aInfo of arr_a) {
        var fs = require('fs');
        if (aInfo == "a") {
            fs.readFile("./debug.json", function (error_file, data_file) {
                if (error_file) {
                    console.log(error_file)
                } else {
                    txs_arr_tmp.push("a");
                }
            });

        } else {
            txs_arr_tmp.push("b");
        }
    }
    return txs_arr_tmp;
}

iterTrans(arr_a).then((txs_arr_tmp) => {

    var content_str = JSON.stringify(txs_arr_tmp);
    console.log(content_str);
})

我希望控制台会打印:

["a","b","a","b","a","b"]

但其实我得到了:

["b","b","b"]

我学习并尝试了一些异步转同步的方法,但我没有成功。而且我必须在readFile中使用异步方法。

那么我怎样才能得到 ["a","b","a","b","a","b"]?谁能给我一些建议?

非常感谢!

【问题讨论】:

  • 看起来您正在尝试获取['a', 'b', 'a', 'b', 'a', 'b'],而不是["a","b","a","a","a","a"]。你能解释一下为什么你期望ba 替换吗?
  • 你能发布一个工作代码sn-p吗?
  • 异步函数中的 readFile 仍然是异步的。使用同步文件读取以确保在返回之前完成构建 txs_arr_tmp。有关如何读取多个文件,请参阅此帖子:stackoverflow.com/questions/37576685/…
  • @IgnacyDebicki 该答案没有读取“同步”文件。它仍然是异步的,只是基于 promise 而不是基于回调。
  • @PatrickRoberts 我知道。这就是问题所在。 for 循环遍历异步文件读取,将 b 放入数组,并在他们有机会完成回调之前返回数组,将适当的值推入军队。因此,他需要在for循环内部使用同步文件读取,这样异步函数只有在读取完所有文件后才返回

标签: javascript node.js asynchronous synchronous


【解决方案1】:

以下是我编写函数的方法。由于您的 Node.js 版本不支持 fs.promises API,您可以使用 util.promisify()fs.readFile() 从回调 API 转换为 Promise API,然后使用 Array.prototype.map() 创建一组 Promise 和await readFile()Promise.all() 并行调用:

const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);

const time_begin = Date.now();
console.log("begin time:" + time_begin);

const arr_a = ['a', 'b', 'a', 'b', 'a', 'b'];

async function iterTrans (arr_a) {
  // array map allows parallel asynchronicity
  const txs_arr_tmp_promises = arr_a.map(async aInfo => {
    // use early return (to avoid nesting large blocks inside if statements)
    if (aInfo !== 'a') return 'b';

    // let await throw here if file error occurs
    const data_file = await readFile('./debug.json');
    return 'a';
  });

  return Promise.all(txs_arr_tmp_promises);
}

iterTrans(arr_a).then(txs_arr_tmp => {
  const content_str = JSON.stringify(txs_arr_tmp);
  console.log(content_str);
}).catch(error => {
  // handle errors here
  console.log(error);
});

【讨论】:

    【解决方案2】:

    您无法将异步转换为同步,但您可以让其余的实现等待异步函数完成

    var time_begin = Date.now();
    console.log("begin time:" + time_begin);
    arr_a = ['a', 'b', 'a', 'b', 'a', 'b']
    
    async function iterTrans(arr_a) {
      var txs_arr_tmp = [];
      for (let aInfo of arr_a) {
        const fs = require('fs').promises;
        if (aInfo == "a") {
          try {
            await fs.readFile("./debug.json")
            txs_arr_tmp.push("a");
          } catch (error) {
            console.log(error)
            var obj_addr = {
              "success": false,
              "error_no": 1,
              "error_info": "err with addrs"
            }
            return res_send.jsonp(obj_addr);
          }
        } else {
          txs_arr_tmp.push("b");
        }
      }
      return txs_arr_tmp;
    }
    
    iterTrans(arr_a).then((txs_arr_tmp) => {
      var content_str = JSON.stringify(txs_arr_tmp);
      console.log(content_str);
    }) 
    

    如果 fs 的承诺方法不可用

    var time_begin = Date.now();
    console.log("begin time:" + time_begin);
    arr_a = ['a', 'b', 'a', 'b', 'a', 'b']
    
    async function iterTrans(arr_a) {
      var txs_arr_tmp = [];
      for (let aInfo of arr_a) {
        let util = require('util');
        const readFile = util.promisify(require('fs').readFile);
        if (aInfo == "a") {
          try {
            await readFile("./debug.json")
            txs_arr_tmp.push("a");
          } catch (error) {
            console.log(error)
            var obj_addr = {
              "success": false,
              "error_no": 1,
              "error_info": "err with addrs"
            }
            // return res_send.jsonp(obj_addr);
          }
        } else {
          txs_arr_tmp.push("b");
        }
      }
      return txs_arr_tmp;
    }
    
    iterTrans(arr_a).then((txs_arr_tmp) => {
      var content_str = JSON.stringify(txs_arr_tmp);
      console.log(content_str);
    })
    

    【讨论】:

    • 感谢您的回答。但我收到了那个错误:TypeError: Cannot read property 'readFile' of undefined
    • @VincentWang 您必须使用旧版本的 Node.js。 The fs.promises API was added in version 10
    • @VincentWang 那么你可以使用let util = require('util'); const readFile = util.promisify(require('fs').readFile);
    猜你喜欢
    • 2018-01-11
    • 2021-10-29
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    • 2013-07-01
    • 2015-06-25
    相关资源
    最近更新 更多