繁体   English   中英

如何在Node.js中编写自定义异步函数

[英]How to write custom async function in Node.js

我是javascript的新手,试图了解异步函数调用。 这是我的js程序:

var notify =  function () {
    console.log('before');
    doPost('data', (res) => {
        console.log('callback received');
    });
    console.log('after');
}
var doPost = function (data) {
    console.log(data);
    while (true) {
        //do nothing
    }    
}
notify();

如果我的理解是正确的,则notify()-> doPost()是异步方式,因此应在“之前”之后立即打印“之后”。 但这不会发生。 我的程序等待无限循环先完成。 我知道我的理解存在漏洞。 请帮忙。

我尝试了以下两个程序:此程序再次显示了同步行为。 打印:-数据之前

 var notify = function () {
    console.log('before');
    doPost('data').then((res) => {
        console.log('callback received');
    });
    console.log('after');

}
var doPost = function (data) {
    console.log(data);
    return new Promise((resolve, reject) => {
        resolve('resolved');
        while (true) {
            //do nothing           
        }
    });
};
notify();

但是,如果我只删除无限运行的while循环,它将开始显示异步行为。 打印:-在收到回调后的数据之前

var notify = function () {
    console.log('before');
    doPost('data').then((res) => {
        console.log('callback received');
    });
    console.log('after');

}
var doPost = function (data) {
    console.log(data);
    return new Promise((resolve, reject) => {
        resolve('resolved');
        while (false) {
            //do nothing           
        }

    });
};
notify();

这是我无法理解的。 任何帮助将不胜感激。

使用回调或Promise不一定意味着某些事情是异步的。 举个例子:

   console.log("before");
   [1, 2, 3].forEach(console.log);
   console.log("after");

这将按顺序记录所有内容,因为.forEach同步调用回调。 但是,还有异步回调,例如setTimeout

 console.log("before");
 setTimeout(function later() {
   console.log("later");
  }, 0);
  console.log("after");

在这里,您将看到“之前”,“之后”,“以后”,因为完成计时器后, later函数将异步执行。 为了获得异步行为,您需要一个“异步根回调”,所有基于异步的回调/承诺也都是异步的。 在Javascript中,只有少数这样的“异步根”,即setTimeoutsetIntervalfetch以及浏览器上的DOM事件处理程序或nodejs上的所有IO。 在您的代码中没有这些,因此,无论您做什么,它都是完全同步的。

要使其表现为异步,请添加异步回调:

function notify() { // function declarations look so much better than function expressions, and they are easier to handle
  console.log('before');
  doPost('data', (res) => {
    console.log('callback received');
  });
  console.log('after');
}

function doPost(data, callback) { // you pass a callback, so you should take it here
  console.log(data);
  setTimeout(callback, 1, "result"); // call back asynchronously
}

notify();

哦, while(true)通常表明您做错了什么。

为什么要编写自己的异步函数? 已经有许多不同的实用程序:

请看这里的例子。 不会有帮助吗? https://caolan.github.io/async/

查看示例,您似乎将异步视为并行执行,因为您期望在另一个线程上运行无限循环时主线程中的代码继续执行。 并行执行是异步操作的一种形式,但是在javascript中,我们通常使用并发执行。

但是同步,异步,并行,并发到底意味着什么?

同步代码最容易使用,因为它可以提供最佳保证:

 /* 1 */ doWorkSync(() => console.log("callback")); /* 2 */ console.log("after doWorkSync"); 

在上面的代码中, doWorkSync是同步函数,我们知道回调函数将在第2行之前执行。

在javascript中通常被称为异步的并发代码给我们带来了更差的保证:

 /* 1 */ doWorkAsync(() => console.log("callback")); /* 2 */ console.log("after doWorkAsync"); 

在上面的代码中,我们保证将在当前同步代码将完全执行之后(即在第2行之后)调用回调函数。但是我们不知道确切的时间。 它可能会立即被调用,但可能会在以后被调用。

但是最难处理的代码是并行代码:

 /* 1 */ doWorkParallel(() => console.log("callback")); /* 2 */ console.log("after doWorkParallel"); 

在上面的代码中,我们无法保证。 回调代码可以在第2行之前同时或稍后运行。 因此,必须以适合任何情况的方式编写代码。

在JavaScript中编写异步(并发)函数的最简单方法是使用Promise

 console.log("first"); Promise.resolve().then(() => console.log("last")); console.log("second"); 

在上面的代码then被执行回调当前同步码从microtask队列运行之后立即。

并行代码可以在带有Worker的JavaScript中执行:

 function parallel() { function work() { block(200); // message from the main thread is logged while this blocks the worker console.log("second"); // logs from the worker can be seen in the browser console function block(time) { const startDate = Date.now(); while (startDate + time > Date.now()) {}; } } new Worker(window.URL.createObjectURL(new Blob([`(${work})()`]), { type: 'application/javascript' })); } function block(time) { const startDate = Date.now(); while (startDate + time > Date.now()) {} } parallel(); // timeout is needed because blob response is handled on the main thread setTimeout(() => { console.log("first"); block(500); // message from parallel is logged while this blocks the main thread console.log("last"); }, 100) 

暂无
暂无

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

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