V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
yazoox
V2EX  ›  JavaScript

阅读源码,无意中看到这到一段,请教一下,这算是同步的还是异步的代码?

  •  
  •   yazoox · 2022-03-24 08:15:06 +08:00 · 5803 次点击
    这是一个创建于 1006 天前的主题,其中的信息可能已经有所发展或是发生改变。

    leran cli 的源代码 https://github.com/lerna/lerna/blob/main/core/command/index.js#L45

    这个 command 的 constructor 里面,

    1. 这种执行方式,是同步的么?
          let chain = Promise.resolve();
    
          chain = chain.then(() => {
            this.project = new Project(argv.cwd);
          });
          chain = chain.then(() => this.configureEnvironment());
          chain = chain.then(() => this.configureOptions());
          chain = chain.then(() => this.configureProperties());
          chain = chain.then(() => this.configureLogging());
          chain = chain.then(() => this.runValidations());
          chain = chain.then(() => this.runPreparations());
          chain = chain.then(() => this.runCommand());
    
    1. 然后上面 1 中的代码,外面套了一层 let runner = new Promise((resolve, reject) => { ... } 后面继续 runer.then(...) 这个是同步还是异步?
    2. command 的 constructor 是同步还是异步?
    3. 该类 Command 的方法,runCommand()呢?
     runCommand() {
        return Promise.resolve()
          .then(() => this.initialize())
          .then((proceed) => {
            if (proceed !== false) {
              return this.execute();
            }
            // early exits set their own exitCode (if non-zero)
          });
      }
    

    看得我好迷糊,也都没有添加 async 关键。

    求指点。

    谢谢!

    第 1 条附言  ·  2022-03-24 18:17:30 +08:00
    谢谢大家的回答。

    明白了很多。
    18 条回复    2022-03-24 18:35:31 +08:00
    chaoschick
        1
    chaoschick  
       2022-03-24 08:19:21 +08:00 via Android
    异步
    ZE3kr
        2
    ZE3kr  
       2022-03-24 08:29:17 +08:00
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

    Promise.prototype.then() 返回的是 Promise ,所以当然是异步了。和 chan = chain.then(async () => await Promise.all([this.configureEnvironment(), this.configureOptions(), ...])) 一样
    ospider
        3
    ospider  
       2022-03-24 08:29:50 +08:00
    async 就是 Promise 的语法糖啊,看到 Promise 基本就是异步。
    MozzieW
        4
    MozzieW  
       2022-03-24 08:30:19 +08:00
    把 chain 的赋值去掉,改写一下容易看。这是啥写法啊,脑筋急转弯呢
    ```
    let chain = Promise.resolve()
    .then(() => {
    this.project = new Project(argv.cwd);
    })
    .then(() => this.configureEnvironment())
    .then(() => this.configureOptions())
    .then(() => this.configureProperties())
    .then(() => this.configureLogging())
    .then(() => this.runValidations())
    .then(() => this.runPreparations())
    .then(() => this.runCommand())
    ```
    huanghui
        5
    huanghui  
       2022-03-24 08:31:35 +08:00 via iPhone
    了解一下 js 事件循环,宏任务和微任务
    ZE3kr
        6
    ZE3kr  
       2022-03-24 08:41:14 +08:00
    刚才回复错了,两中写法不一样。上面那个代码效果**约**等于

    chain = await chain.configureEnvironment()
    chain = await chain.configureOptions()
    ...

    是异步(指不会阻塞其他事件),但是每一步都是顺序执行的(指非并行)

    Q: 然后上面 1 中的代码,外面套了一层 let runner = new Promise((resolve, reject) => { ... } 后面继续 runer.then(...) 这个是同步还是异步?

    A: 取决于什么时候 call 的 resolve 。如果是 chan.then(resolve)那就顺序执行(指非并行)。但也是异步(指不会阻塞其他事件)

    Q: command 的 constructor 是同步还是异步?

    看你怎么定义异步同步了。我一般把返回的是 Promise 或者 async 函数叫做异步,无论函数内本身有没有调用异步

    Q: 该类 Command 的方法,runCommand()呢?

    你仔细看一下,是和 1 一样的,只是没有 chain 这个变量而已了。
    eason1874
        7
    eason1874  
       2022-03-24 08:50:54 +08:00
    异步。这是链式写法,你在中间打印 chain 对象看一眼就知道了,是个还没完成的 Promise 对象
    retrocode
        8
    retrocode  
       2022-03-24 09:28:39 +08:00
    异步的,这写法迷惑性太大,第一眼差点绕进去

    ```js

    let a = Promise.resolve();
    let b = a.then(() => {
    this.project = new Project(argv.cwd);
    });
    let c = b.then(() => this.configureEnvironment());
    let d = c.then(() => this.configureOptions());
    let e = d.then(() => this.configureProperties());
    let f = e.then(() => this.configureLogging());
    let g = f.then(() => this.runValidations());
    let h = g.then(() => this.runPreparations());
    let i = h.then(() => this.runCommand());

    ```

    脑补成这样会好理解些, 在转义下就是 6 楼的逻辑了
    Lax
        9
    Lax  
       2022-03-24 09:36:12 +08:00
    这是什么写法,把同步的链式操作拆成多个异步操作,仍然是链式操作?
    KrisWuSkrSkr
        10
    KrisWuSkrSkr  
       2022-03-24 09:55:29 +08:00
    promise 的同步是指什么样的。
    acthtml
        11
    acthtml  
       2022-03-24 10:00:45 +08:00
    只要是 promise 就是异步,执行顺序不能保证,
    promise 可通过.then 操作链顺序执行,可以利用 async/await 整个语法糖来顺序执行。

    1. 等同于链式写法。
    2 、3 同一个问题,整个方法体返回的是 promise 而已。promise 的执行顺序见上面。
    Kasumi20
        12
    Kasumi20  
       2022-03-24 10:12:14 +08:00
    这些任务是同步的,搞不懂干嘛这样写,为了某一项出错后其它任务就停止了,然后用.catch 去处理错误?用异常不也一样?
    en20
        13
    en20  
       2022-03-24 10:44:19 +08:00
    是异步,但会按顺序执行
    xianyu191031
        14
    xianyu191031  
       2022-03-24 10:48:18 +08:00
    建议不要纠结同步异步,Event Loop 的机制过程熟读一下 这部分就很好理解了
    libook
        15
    libook  
       2022-03-24 12:35:10 +08:00
    突然发现这个问题对于 JS 熟练开发者来说很容易理解,但解释起来可能会很复杂。
    我写了又删,删了又写……

    异步和同步,同时存在于两个维度,一个是 JS 执行维度,另一个是业务关系维度。

    JS 执行上来说,同步执行就是按代码顺序执行,后写的表达式总会等待先写的表达式执行完再执行;
    异步执行就是可以不按代码顺序执行,而是按需要执行,同时也不需要让后面的表达式等着它执行完成;
    有的时候我们在异步执行的同时还需要一个异步操作等待另一个异步操作,JS 就提供了描述这种等待关系的机制(如 Promise.prototype.then() 和 await ),我习惯称之为“异步操作同步化”。

    业务关系上来说,异步和同步是相对的,两个业务之间互相不依赖,就是异步关系,有依赖就是同步关系。

    题主给的例子里代码很多,也有 Promise ,但其实核心还是回调函数,Promise 只是提供了一种隐式调用回调函数的机制而已,async 是 Promise 的语法糖,所以也是一样的。

    这个思路基本就是,因为回调函数的函数体内容是按需执行的,外层的执行完成不依赖于回调函数内部执行完成,所以可以简单判断为回调函数外的部分以及回调函数本身的声明是同步执行的,回调函数内部程序相对外部作用域来说是异步执行的。

    比如
    chain = chain.then(() => {
    this.project = new Project(argv.cwd);
    });
    可以拆成三部分,一部分是回调函数外的部分,即 chain = chain.then();
    第二部分是回调函数本身的函数声明部分,即 ()=>{}
    第三部分是回调函数的函数体内容部分,即 this.project = new Project(argv.cwd);

    前两部分是按顺序执行的,是同步;第三部分是按需执行的,且前两部分不依赖这一部分的执行结果,是异步。
    libook
        16
    libook  
       2022-03-24 12:48:12 +08:00
    @libook #15 我后半部分写的基本上是按照 JS 执行上来说的。
    但从业务上来说,必须等 this.configureEnvironment() 执行完才能执行 this.configureOptions() ,这两个业务的关系是同步关系;而 chain = chain.then()不需要等 this.configureEnvironment()执行完成,所以这两个是异步关系;我们因为存在着异步关系所以需要使用 JS 异步语法来写,但为了同时满足业务上的同步关系需要使用 then 来描述等待关系。

    也就是说 JS 执行维度和业务关系维度,异步和同步的辨析可能是不同的。
    zhouyg
        17
    zhouyg  
       2022-03-24 17:19:15 +08:00
    代码是异步执行,但在逻辑上是按顺序的
    guanhui07
        18
    guanhui07  
       2022-03-24 18:35:31 +08:00
    async 就是 Promise 的语法糖
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2966 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 13:26 · PVG 21:26 · LAX 05:26 · JFK 08:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.