Javascript 异步代码,它是如何工作的?承诺和回扣

Javascript 异步代码,它是如何工作的?承诺和回扣,javascript,asynchronous,ecmascript-6,promise,asynccallback,Javascript,Asynchronous,Ecmascript 6,Promise,Asynccallback,我试着在网上找到答案,并且做了一部分。但我仍然不能完全理解JS如何运行ansyncronous代码 我对事物的看法: JS给了我们异步编程的能力。这意味着我们可以开始第一项任务,然后当一项任务正在进行时,我们可以开始第二项任务,等等。 在js可以启动第二个任务之前,它应该从上一个任务中释放出来。可通过两种方式实现: js自己完成任务(只应由js处理的代码) 例如,js可以启动应该由文件系统处理的任务。在本例中,js执行其工作,将任务传递到文件系统,并开始处理其他排队的任务。释放js并返回结果后

我试着在网上找到答案,并且做了一部分。但我仍然不能完全理解JS如何运行ansyncronous代码

我对事物的看法:

JS给了我们异步编程的能力。这意味着我们可以开始第一项任务,然后当一项任务正在进行时,我们可以开始第二项任务,等等。 在js可以启动第二个任务之前,它应该从上一个任务中释放出来。可通过两种方式实现:

  • js自己完成任务(只应由js处理的代码)
  • 例如,js可以启动应该由文件系统处理的任务。在本例中,js执行其工作,将任务传递到文件系统,并开始处理其他排队的任务。释放js并返回结果后,js可以继续执行该任务
因此,我们无法通过编写下一个代码来实现异步:

function doSth( callback ) {
    let arr = [];

    for ( let i=1e6; i > 0; i-- )
        arr.push( i );

    callback();
}

doSth( console.log.bind( null, 'I am callback' );
console.log( 'just a line' );
由于doSth()只包含js的工作,它将首先完成,然后只显示“仅一行”?所以它不是异步的,对吗? 但若我们将文件系统任务替换为循环,那个么我们将拥有异步函数吗

还有一个问题:承诺真的是异步的吗?它们怎么可能是异步的(我的意思是,在承诺处理时可以处理其他任务),或者承诺只是模仿异步代码? *我知道,还有更多的承诺

也许我只是不懂一些基础知识?如果你能给我解释一下,让我的问题更清楚,我会很高兴的。

要回答您的一个主要问题,异步与文件系统无关。仍然是Javascript。引用我推荐的那本书:

异步是“当程序的一部分现在运行,而另一部分稍后运行时——此时和以后之间存在一个间隙,此时程序不会主动执行。”

考虑您的代码:

function doSth(callback) {
  let arr = [];
  for (let i=1e6; i > 0; i--){
    arr.push(i);
  }
  callback();
}

doSth(console.log.bind(null, 'I am callback'));
console.log('just a line');
这将输出

我正在回电话

然后

只是一句话

但是,如果您将代码更改为:

function doSth(callback) {
  let arr = [];
  for (let i=1e6; i > 0; i--){
    arr.push(i);
  }
  setTimeout(callback, 0);
}

doSth(console.log.bind(null, 'I am callback'));
console.log('just a line');
你会得到

只是一句话

然后

我正在回电话

它本质上与调用回调函数的函数有关。“doSth”不是一个异步函数,不管for循环需要多长时间。但是,在第二个示例中,setTimeout是调用回调函数的函数,而setTimeout是一个异步函数,它在同步代码的其余部分之后运行,因为这是它的工作方式。另一个常见的异步函数是任何类型的AJAX请求,提供给它的回调也将在任何其他同步代码之后调用

要回答您的一个主要问题,异步与文件系统无关。仍然是Javascript。引用我推荐的那本书:

异步是“当程序的一部分现在运行,而另一部分稍后运行时——此时和以后之间存在一个间隙,此时程序不会主动执行。”

考虑您的代码:

function doSth(callback) {
  let arr = [];
  for (let i=1e6; i > 0; i--){
    arr.push(i);
  }
  callback();
}

doSth(console.log.bind(null, 'I am callback'));
console.log('just a line');
这将输出

我正在回电话

然后

只是一句话

但是,如果您将代码更改为:

function doSth(callback) {
  let arr = [];
  for (let i=1e6; i > 0; i--){
    arr.push(i);
  }
  setTimeout(callback, 0);
}

doSth(console.log.bind(null, 'I am callback'));
console.log('just a line');
你会得到

只是一句话

然后

我正在回电话


它本质上与调用回调函数的函数有关。“doSth”不是一个异步函数,不管for循环需要多长时间。但是,在第二个示例中,setTimeout是调用回调函数的函数,而setTimeout是一个异步函数,它在同步代码的其余部分之后运行,因为这是它的工作方式。另一个常见的异步函数是任何类型的AJAX请求,提供给它的回调也将在任何其他同步代码之后调用

我想你说得对

函数
doSth
是同步的,将阻塞主线程,直到完成。您只提供回调API,但这并不意味着它将神奇地变成异步的

事实是,除非您使用定义为异步的核心JS函数(例如,
fs.readFile
setTimeout
$.ajax({…}).done
),否则您编写的所有JS代码都是同步的。没有它们,你就无法创建异步行为,你必须从头开始编写自己的JS核心,使用事件循环(事实上,我鼓励你用谷歌搜索并研究
javascript事件循环是什么,我相信它会为你澄清很多事情,并让你更好地了解核心中发生的事情)。所有第三方lib都实现了异步行为,这仅仅是因为它们使用这些核心函数并用自己的代码包装它们,从而提供了更优雅和更高级的api


承诺也是如此。是的,它们是异步的,但只有在用异步代码填充它们时才是如此。事实上,它们有一些额外的开销,并且不会立即运行代码,但是如果一个承诺只包含同步代码,那么它的最终执行将阻塞主线程,直到它完成。

我认为您是对的

函数
doSth
是同步的,将阻塞主线程,直到完成。您只提供回调API,但这并不意味着它将神奇地变成异步的

事实是,除非您使用定义为异步的核心JS函数(例如,
fs.readFile
setTimeout
$.ajax({…}).done
),否则您编写的所有JS代码都是同步的。没有它们,你就无法创建异步行为,你必须从头开始编写自己的JS核心,使用事件循环(事实上,我鼓励你用谷歌搜索并研究
javascript事件循环是什么,我相信它会为你澄清很多事情,并让你更好地了解核心中发生的事情)。所有第三方lib都实现了异步行为,因为它们使用这些核心函数