Vim 执行异步任务

作者: xOuOx | 来源:发表于2017-03-18 13:10 被阅读215次

概述

Vim从8.0版本开始支持异步IO,通过job来开始执行另一个进程,通过channel来进行进程通信。

只要Vim的版本高于8.0,并且在编译时有+channel+job的feature,就可以通过使用Vim的异步支持来让插件或脚本拥有更好的体验,比如异步编译使Vim在编译时不在阻塞、异步语法高亮来时Vim获得更快的速度等。

使用

has('channel')
has('job')

来判断Vim是否有相关支持。

我有一个在Vim中翻译单词的插件,但在网络不好的情况下翻译会阻塞正常的浏览,本文是我希望插件可以进行异步翻译而进行的学习笔记,只简单记录了job的工作方式,更多详细内容请在Vim中使用:help channel查看。

job的工作方式

job可以理解为Linux中的进程,通过:

job_start(command, {options})

可以在这个一个进程(job)中执行command,job_start返回job对象,使用

let channel = job_getchannel(job)

可以获得与job关联的channel用于通信,本文不再讨论。

command是要执行的外部命令,如果要获取命令的执行结果或状态,可以使用options设置回调函数来完成。

处理任务输出

捕获每次输出

如果command产生输出,可以使用out_cb定义回调函数处理输出:

func! Handler(channel, msg)
    " deal with msg 
endfunc

let job = job_start(command, {"out_cb", "Handler"})

cb表示callback

或者可以使用ch_read(job)或者cd_readraw(job)读取job产生的输出

捕获结束输出

如果不想处理任务的中间输出,可以使用close_cb定义回调函数获取结束job的输出:

func! CloseHandler(channel)
  while ch_status(a:channel, {'part': 'out'}) == 'buffered'
    echomsg ch_read(a:channel)
  endwhile
endfunc

let job = job_start(command, {'close_cb': 'CloseHandler'})
处理任务的错误输出

out_cb指定的回调函数不会接收标准错误输出,可以使用err_cb指定的回调函处理错误输出:

let job = job_start(command, {"out_cb": "Handler",
        \                     "err_cb": "ErrHandler"})

callback指定的回调函数既可以接收错误输出,也可以接收普通输出

let job = job_start(command, {"callback": "MyHandler"}) 

控制job

得到job状态:

job_status(job)

停止job:

job_stop(job)

示例

如果我们有一个耗时3s的外部程序要执行,程序执行之后输出日期,如果使用过去的方法,将其映射到<F3>键(这里使用sleep 3s模拟该耗时程序):

nnoremap <F3> :!/bin/bash -c 'sleep 3s; date'<CR>

点击<F3>后Vim将有3s处于阻塞状态,无法进行任何操作。

接下来使用异步来处理这个程序:

" 回调函数
func! Handler(channel, msg)
    echo a:msg
endfunc

" 执行job
func! GetDate()
    call job_start(['/bin/bash', '-c', 'sleep 3s; date'], {'callback': 'Handler'})
endfunc

nnoremap <F3> :call GetDate()<cr>

此时再点击<F3>,Vim将不会阻塞,可以继续进行操作,并在3s后输出日期。

相关文章

  • Vim 执行异步任务

    概述 Vim从8.0版本开始支持异步IO,通过job来开始执行另一个进程,通过channel来进行进程通信。 只要...

  • 【javaScript练习】2021-02-23

    javaScript 作用域,异步执行,requestAnimationFrame 微任务,宏任务,异步执行 Ar...

  • js执行顺序总结

    流程图 首先执行同步任务,异步任务会插入到异步队列中。同步任务执行完毕,查询是否有异步任务,回到主任务执行。 微任...

  • 深入浅出Javascript事件循环机制-上(转)

    浅薄概念 Javascript是单线程,执行任务时,分同步任务和异步任务,执行同步任务时放入栈中执行,执行异步任务...

  • 异步任务执行

    《深入理解ES6》阅读随笔 在使用 JavaScript 写程序的过程中,会遇到一些异步调用的情况,如果只是单层的...

  • NSQ 消息队列

    异步任务与消息队列 同步任务:一定要等任务执行完了,得到结果,才执行下一个任务。 异步任务:不用等任务执行完,直接...

  • GCD小总结

    单例模式 串行队列同步/异步执行任务 并发队列同步/异步执行任务 队列组 延时执行 barrier

  • c#-异步编程模型-代码示例

    异步编程,当有Task完成就执行 手动执行取消任务 超时取消任务 异步文件读写

  • nextTick、setImmediate、promise.re

    执行队列(同步) 任务队列(异步事件) 每当异步任务完成后会在任务队列中添加一个关联事件,待执行队列任务执行完成...

  • 02、NodeJS-基础

    一、异步编程 异步操作 Node大量采用异步操作,即任务不是马上执行,而是直接插入任务队列的尾部,等前面任务执行完...

网友评论

  • Homer1ynn:你好,我用python的Flask框架,写了一个app的后端程序,想试着执行一下,不知道可行吗?如果执行一个正常的python脚本文件是没有问题的(比如打印'hello world'),执行这个会阻塞,如果可行的话,有什么办法吗?

本文标题:Vim 执行异步任务

本文链接:https://www.haomeiwen.com/subject/xbpunttx.html