我试图在网上找到答案,并且部分地做了。但我还是不能完全理解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的工作,它将首先完成,然后只显示一行'?所以它不是同步的,对吧? 但是如果我们将文件系统任务放在循环中,我们将具有异步功能吗?
还有一个问题:承诺真的是同步吗?它们如何是异步的(我的意思是,在承诺处理时可以处理其他任务),或者承诺只是模仿异步代码? *我知道,还有额外的承诺队列。
Maby我只是不了解一些基础?如果你能解释我,让我的问题更加明确,我会很高兴。
答案 0 :(得分:0)
Watch this playlist for a light overview of asynchronous Javascript.
But if you really want to understand all the details, read this book.
要回答您的一个主要问题,异步与文件系统无关。它仍然是Javascript。引用我推荐的那本书:
Asynchrony是“当你的程序的一部分现在运行,程序的另一部分稍后运行 - 现在和之后的程序没有正在执行的程序之间存在差距。”
考虑你的代码:
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');
你会得到
只是一行
然后
我是回电
它基本上与调用回调的函数有关。无论for循环需要多长时间,“doSth”都不是异步函数。但是,在第二个例子中,setTimeout是调用你的回调的函数,而setTimeout是一个异步函数,它在你的同步代码的其余部分之后运行,因为它是它的工作方式。另一个常见的异步函数是任何类型的AJAX请求,并且提供给它的回调也将在任何其他同步代码之后调用。
答案 1 :(得分:0)
我认为你做得对。
函数doSth
是同步的,将阻塞主线程直到它完成。您只提供回调API,但这并不意味着它会神奇地变为异步。
事实是,您编写的所有JS代码都是同步的,除非您使用定义为异步的核心JS函数(例如fs.readFile
,setTimeout
,$.ajax({...}).done
)。如果没有它们,你就无法创建异步行为,你必须从头开始编写自己的JS核心,并使用事件循环(事实上,我鼓励你去研究javascript event loop
是什么,我相信它会为你澄清很多东西,并会让你更好地了解核心中发生的事情。所有第三方库都实现了异步行为,因为它们使用这些核心功能并使用自己的代码包装它们,从而提供更优雅和更高级别的API。
这同样适用于承诺。是的,它们是异步的,但是只要你用异步代码填充它们。实际上,它们有一些额外的开销并且不会立即运行代码,但是如果单个promise只包含同步代码,那么它的最终执行将阻塞主线程直到它完成。