美文网首页微信小程序微信小程序微信小程序开发者
微信小程序中使用co来处理异步流程

微信小程序中使用co来处理异步流程

作者: 一斤代码 | 来源:发表于2016-12-23 15:52 被阅读1935次

    co是一个基于ES6 Generator特性实现的【异步流程同步化】写法的工具库。

    co需要使用Promise特性,所以,我们先来创建一个使用Promise来处理的异步方法:

    function myAsyncFunc() {
      return new Promise(function (resolve, reject) {
        setTimeout(function () {
          console.log("myAsyncFunction done!");
          resolve({ 
            data: "Hello,World" 
          })
        }, 2000);
      });
    }
    

    然后,直接使用这个方法的话,就会如下,使用了then/catch的回调方式来处理调用结果和异常处理:

    myAsyncFunc().then(function (result) {
      console.log(result.data);  //Hello,World
    }).catch(function (err) {
      //...
    });
    

    而如果是使用co的话,则会像这样:

    co(function *() {
    
      try {
        var result = yield myAsyncFunc();
        console.log(result.data); //Hello,World
      } catch(e) {
      }
    
    });
    

    这样的写法,是不是就是我们非常熟悉的,比较符合逻辑思维习惯的同步写法了?

    关于co的用法,在本文中我就不多展开了,有兴趣的朋友可以自行搜索相关资料。我今天要讲的是,如何在小程序环境下面成功的使用co。

    1. 开启语言转译选项

    由于要使用到ES6的generator,而又要为了兼容性,我们必须对ES6的语法进行降级转译,变成ES5。

    开启语言转译选项

    2. 引入generator支撑库

    经过转译后的代码,需要依赖一个regeneratorRuntime,才能支持generator特性。Facebook开源的一个regenerator就是这样一个库,Github地址:https://github.com/facebook/regenerator/

    你可以通过npm来下载这个regenerator库:

    npm install regenerator
    

    然后将下载文件中名为regenerator-runtime.js的文件拿出来,放到我们的小程序代码中去。

    3.下载co和Promise库

    接着,通过npm下载co库:

    npm install co
    

    将下载文件中名为co.js文件拿出来,放到我们的小程序代码中去。

    因为需要依赖Promise,所以我们需要引入一个Promise实现库。在此我们选用一个小而兼容性好的库es6-promise。同样可以通过npm下载:

    npm install es6-promise
    

    将es6-promise.js放到我们的小程序代码中。

    4.引入小程序代码中

    使用前,将这些库正确的引入我们的代码:

    const Promise = global.Promise = require('../../libs/es6-promise')
    const regeneratorRuntime = global.regeneratorRuntime = require('../../libs/regenerator-runtime')
    const co = require('../../libs/co')
    

    好了,接下来就可以开始愉快的使用co进行编程了。

    相关文章

      网友评论

      • 金逸凌云:大神,我再请教一个问题,再不用generator这个方案之前,为了无限加载避免多次请求接口,立了一个flag(this.data.loadState),代码类似:
        // 下滑加载更多
        lower: function(e){
        // 为什么是*12?
        if(this.data.loadState || (this.data.options.pageNo)*10 >= this.data.courseListTotal) return;
        this.data.options.pageNo++;
        this.loadSearchData(function(data){
        this.data.loadState = false;
        this.setData({
        "courseList": this.data.courseList.concat(data.courseList)
        })
        }.bind(this));
        }

        在请求接口时把flag改成true,在请求success后改成false么,现在换成yield之后是像我现在这样写可以吗?
        app.co(function* (){
        try{
        console.log(that.data.tagId)
        that.data.loadState = true
        var params = {
        tagId: that.data.tagId,
        pageNo: that.data.pageNo,
        }
        var result = yield app.getApi('get', 'https://yoururl', params)
        that.data.loadState = false
        console.log(1, result)
        that.setData({
        excellentcourse: that.data.excellentcourse.concat(result.data.courseList),
        courseListTotal: result.data.total
        })
        } catch(e) {
        }
        })
        ,对yield还是没有深入理解呀。。是不是不需要这样控制了,因为代码现在是同步执行了
        金逸凌云:@一斤代码 好的,非常感谢,如果有加载数据的动画该怎么体现呢,我的getApi方法已经封好了。
        getApi里是这样的
        function getApi(method, url, params={}, ){
        method = method.toUpperCase()
        var methodHeader = {}
        if(method == "POST"){
        methodHeader = { "content-type": "application/x-www-form-urlencoded" }
        } else if (method == "GET") {
        methodHeader = { 'content-type': 'application/json' }
        }
        return new Promise((resolve, reject) => {
        wx.request({
        url: url,
        method: 'GET',
        header: methodHeader,
        data: params,
        success: function (json) {
        resolve(json)
        },
        fail: function (json) {
        reject(json)
        }
        })
        })

        }

        module.exports = getApi

        不写在success里面我不会了~~
        一斤代码:但是你第一段代码里的flag,它有防止重复调用的功能,你第二段代码里没有体现出来这个功能,如果需要的话,第二段代码里可以加上类似的控制代码:

        if (that.data.loadState) return; //loading中,忽略重复调用
        一斤代码:你这样写是可以的,不过你下面用了co的这段代码里那个flag可以去掉了。
      • 金逸凌云:楼主,npm install之后,co文件夹里只有个index.js。对应文中的co.js?
        regenerator-runtime比较迷茫,文件夹有两个,regenerator和regenerator-runtime。且里面的文件各有一个runtime.js和runtime-module.js。原谅我前端技术还不到看懂源码的程度,不知道该怎么引,求助
        金逸凌云:@一斤代码 谢谢您的及时回复,现在可以运行起来啦:smiley:
        一斤代码:嗯,由于这两个库的升级,文件名有变动。co的话就是用这个index.js,regenerator的话用runtime.js
      • 21fe9dd84d55:为什么使用co不需要gulp,而使用async需要gulp
        一斤代码:因为使用co的话,使用到的是ES6的特性(Generator),微信开发者工具自带了可以转换ES6到ES5的功能;而async/await是ES7的特性,微信开发者工具没法转换,所以要额外借助gulp来通过babel与其ES7转换插件来转换语法。
      • 知晓程序:你好!我们是爱范儿旗下专注于小程序生态的公众号知晓程序(微信号 zxcx0101)。我们很赞赏你的文章,希望能获得转载授权。授权后,你的文章将会在知晓程序社区(minapp.com)、爱范儿、AppSo 等渠道发布,我们会注明来源和作者姓名。
        知晓程序:@一斤代码 https://minapp.com/thread/11965/ 转载后的链接附上 感谢~
        知晓程序:@一斤代码 嗯嗯好的~非常感谢~
        一斤代码:@知晓程序 可以的。不过务必注明“一斤代码”的名称及原文地址。我发现有些转发的朋友很不地道,直接把文章复制过去就变自己的了。

      本文标题:微信小程序中使用co来处理异步流程

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