异步承诺返回函数的同步与异步执行

时间:2020-07-26 09:10:04

标签: javascript promise event-loop

在制作返回promise的异步函数时,在每个实现中我都看到了这种做法:

function asyncFunction() {
 return new Promise((resolve,reject) => {
  // the function code
  if (condition) resolve()
  else reject()
 })
}

换句话说,executor函数中的函数代码是同步运行的,并且仅答应建立和回调调用是异步完成的。这对我来说是违反直觉的,因为当我想到一个异步函数时,我想到了一个函数,该函数在执行时立即返回并推迟其操作供以后使用。这是一个示例:

function asyncFunction() {
 return new Promise((resolve,reject) => {
  setTimeout(() => {
   // the function code
   if (condition) resolve()
   else reject()
  }, 0)
  
 })
}

这意味着该函数的代码将在任务中执行,并且在返回的promise上注册的所有回调将作为微任务运行。该函数立即返回,并且不会使线程饿死。

我现在有几个问题。

  1. 我的推理是否正确/有意义,或者我没有看到一些极端情况?
  2. 异步功能的特征是什么?我看到两个表征异步函数的候选参数:1.立即返回并在以后运行其计算;以及2.回调在以后/异步运行。对我而言,唯一能表征该功能的是第一点,但是正如我在所有代码中所见,唯一重要的是回调是异步运行的。
  3. 使用我的代码版本而不是第一个版本是否有优点/缺点?

2 个答案:

答案 0 :(得分:1)

承诺是管理异步代码而不是使代码异步的工具。

您的第一个示例根本不应该使用promise。该函数所做的所有事情都是阻塞的。使用诺言只会增加复杂性。 (例外是如果您正在编写代码以匹配有时用于异步操作的接口)。

您的第二个示例也毫无意义(至少几乎总是如此)。添加了 just 超时,以使事件循环在函数外部继续进行,然后稍后再次接收。此 可能很有用(例如,允许浏览器在耗时之前重绘窗口),但是方法应该是:

  1. 在下一个操作运行之前,我需要让窗口重新粉刷
  2. 我将在该操作之前执行超时
  3. 我将使用Promise管理该代码

…,而您的代码似乎正在扭转这种局面,从承诺开始,并试图证明其合理性。

如果您有一些耗时的代码要运行,并且不想让它阻塞主事件循环,那么您可能应该使用 worker ,以便它在另一个线程上运行。可能您将使用Promise处理该代码,将其结果发送回主事件循环。

答案 1 :(得分:0)

我想总结一下我从@Bergi和@Quentin的答案和评论中学到的知识。我现在的理解如下:

异步函数的特征仅在于它立即返回(可能不执行某些同步操作,这是无关紧要的),并且最重要的是,它以非阻塞方式等待返回用于通知的值结果准备就绪时,等待其通知的订阅者。此外,该功能执行的操作可能会通过以下方式执行:

  1. 线程阻塞,即如我所提供的示例
  2. 非阻塞,并发执行(网络内容,文件读取)
  3. 无阻塞,以后再推迟,例如像我的第二个示例一样,由setTimeout推迟

所有三个示例:

第一:

/**
  Compute the result synchronously, return immediately, and resolve with a value later, calling the callback
*/
function first(cb) {
 // synchronous code
 value = 0;
 setTimeout(() => cb(value), 0) 
} 

此示例的另一个示例:

/*
Immediately resolve the promise synchronously, and then call the callback with value
*/
function first(){
 const value = 0;
 return Promise.resolve(value);
}

first().then((value) => {})

第二:

function second() {
  return Promise.resolve(
    fetch('some url'))
    .then(response => response.json())
}

第三:

/*
 Return immediately, perform the function code later, and resolve with a value later
*/
function third() {
 return new Promise((resolve,reject) => {
  setTimeout(() => {
   // the function code
   if (condition) resolve()
   else reject()
  }, 0)
  
 })

主要功能全部返回,将结果传递给回调或以非阻塞方式解决。

请随时纠正我,我会尽我所能来理解它。谢谢。