如何为 Node.js 编写异步函数

IT技术 javascript asynchronous node.js
2021-01-23 05:04:31

我试图研究应该如何编写异步函数。在翻阅了大量文档之后,我仍然不清楚。

如何为 Node 编写异步函数?我应该如何正确实现错误事件处理?

问我的问题的另一种方法是:我应该如何解释以下函数?

var async_function = function(val, callback){
    process.nextTick(function(){
        callback(val);
    });
};

另外,我在 SO(“如何在 node.js 中创建非阻塞异步函数?”)发现这个问题很有趣。我觉得还没有人回答。

6个回答

您似乎将异步 IO 与异步函数混淆了。node.js 使用异步非阻塞 IO,因为非阻塞 IO 更好。理解它的最好方法是观看 ryan dahl 的一些视频。

如何为 Node 编写异步函数?

只需编写普通函数,唯一的区别是它们不会立即执行,而是作为回调传递。

我应该如何正确实现错误事件处理

通常,API 会给您一个回调,并将 err 作为第一个参数。例如

database.query('something', function(err, result) {
  if (err) handle(err);
  doSomething(result);
});

是一种常见的模式。

另一种常见的模式是on('error'). 例如

process.on('uncaughtException', function (err) {
  console.log('Caught exception: ' + err);
});

编辑:

var async_function = function(val, callback){
    process.nextTick(function(){
        callback(val);
    });
};

上述函数调用时

async_function(42, function(val) {
  console.log(val)
});
console.log(43);

42异步打印到控制台。特别是process.nextTick在当前事件循环调用堆栈为空后触发。这调用堆栈是空后async_functionconsole.log(43)已经运行。所以我们打印 43 然后是 42。

您可能应该对事件循环进行一些阅读。

我认为您关于异步 IO 的说法“更好”太笼统了。从这个意义上说是的,但总体而言可能并非如此。
2021-03-22 05:04:31
我看过达尔的视频,但我似乎没有掌握我害怕的问题。:(
2021-04-04 05:04:31
感谢堡垒的见解。我现在更清楚我所缺乏的知识。:) 顺便说一下,您的最后一个示例有所帮助。
2021-04-06 05:04:31
在您的第一个代码示例中,您检查了 err 参数,但之后没有返回。如果出现错误,代码将继续运行,并可能导致应用程序出现严重问题。
2021-04-08 05:04:31
@Kriem 查看更新的答案并阅读有关事件循环的信息
2021-04-11 05:04:31

仅仅通过回调是不够的。例如,您必须使用 settimer 来使函数异步。

示例: 非异步函数:

function a() {
  var a = 0;    
  for(i=0; i<10000000; i++) {
    a++;
  };
  b();
};

function b() {
  var a = 0;    
  for(i=0; i<10000000; i++) {
    a++;
  };    
  c();
};

function c() {
  for(i=0; i<10000000; i++) {
  };
  console.log("async finished!");
};

a();
console.log("This should be good");

如果您将运行上面的示例,这应该很好,必须等到这些功能完成才能工作。

伪多线程(异步)函数:

function a() {
  setTimeout ( function() {
    var a = 0;  
    for(i=0; i<10000000; i++) {
      a++;
    };
    b();
  }, 0);
};

function b() {
  setTimeout ( function() {
    var a = 0;  
    for(i=0; i<10000000; i++) {
      a++;
    };  
    c();
  }, 0);
};

function c() {
  setTimeout ( function() {
    for(i=0; i<10000000; i++) {
    };
    console.log("async finished!");
  }, 0);
};

a();
console.log("This should be good");

这将是真正的异步。这应该会在异步完成之前写好。

你应该看这个:Node Tuts 第 19 集 - 异步迭代模式

它应该回答你的问题。

如果你知道一个函数会返回一个 promise,我建议你使用 JavaScript 中新的 async/await 特性。它使语法看起来同步但异步工作。当您将async关键字添加到函数时,它允许您await在该范围内Promise:

async function ace() {
  var r = await new Promise((resolve, reject) => {
    resolve(true)
  });

  console.log(r); // true
}

如果函数不返回Promise,我建议将其包装在您定义的新Promise中,然后解析您想要的数据:

function ajax_call(url, method) {
  return new Promise((resolve, reject) => {
    fetch(url, { method })
    .then(resp => resp.json())
    .then(json => { resolve(json); })
  });
}

async function your_function() {
  var json = await ajax_call('www.api-example.com/some_data', 'GET');
  console.log(json); // { status: 200, data: ... }
}

底线:利用 Promise 的力量。

这里要记住的是,promise 的主体仍然是同步执行的。
2021-03-19 05:04:31

试试这个,它适用于节点和浏览器。

isNode = (typeof exports !== 'undefined') &&
(typeof module !== 'undefined') &&
(typeof module.exports !== 'undefined') &&
(typeof navigator === 'undefined' || typeof navigator.appName === 'undefined') ? true : false,
asyncIt = (isNode ? function (func) {
  process.nextTick(function () {
    func();
  });
} : function (func) {
  setTimeout(func, 5);
});
@Omer 这就是生活。
2021-03-14 05:04:31
4 票反对,甚至没有一条建设性评论.. :\
2021-03-27 05:04:31
@NorbertoBezi 也许代码对您来说是不言自明的,但对发布答案的人来说却不是。这就是为什么在拒绝投票时进行解释总是一个好习惯的原因。
2021-04-10 05:04:31