7行代码实现异步函数顺序执行-No Callback

首先假设我们有两个函数,分别按顺序被调用,但是他们都会操作一个相同的变量,第一个函数式为这个变量赋值,第二个函数是使用这个变量:代码如下

var value;
var A = function() {
    setTimeout(function() {
        value = 10;
    }, 200);
}
var B = function() {
    console.log(value);
}

如果我们先后调用A() ,B() 我们将会得到输出结果为 undefined,因为函数A式异步的设置变量的值,在执行B的时候,还没有为value赋值,但是我们可以给A传递一个回调函数,带赋值之后执行这个函数,如下

var value;
var A = function(callback) {
  setTimeout(function() {
    value = 10;
    callback();
  }, 200);
};
var B = function() {
  console.log(value);
};

A(function() {
  B();
});

这种方式是可行的,但是假设,如果我要执行四个甚至更异步的方法,这样一直传递回调函数的话将会让代码变得杂乱,并且代码也会失去美观,于是这就是传说中的callback hell,就像这样

A(function() {
    B(function(){
         C(function(){
                  D(function(){
                      E();
                  });
              });
          });
        });

可以考虑写一个小的函数,来帮助我们来完成这个过程,首先从最简单的开始

var queue = function(funcs) {

}

我们可以通过queue([A,B]);分别实现A和B的顺序调用。分别获得每个函数,然后执行

var queue = function(funcs) {
    var f = funcs.shift();
    f();
}

如果执行这些代码话,将会得到如下的异常TypeError: undefined is not a function.,因为A需要接受一个回调函数作为参数,但是并没有传递参数,所以会报错了,下面定义一个next函数作为A的参数进行传递

var queue = function(funcs) {
    var next = function() {
        // ...
    };
    var f = funcs.shift();
    f(next);
};

next函数是在A执行结束之后执行的,这样只是执行了函数A,如果要执行数组里面的每一个函数可以做如下调整

var queue = function(funcs) {
    var next = function() {
        var f = funcs.shift();
        f(next);
    };
    next();
};

到此为止我们基本上已经实现了我们的目标了。通过queue([A,B]);可以实现A和B的顺序执行,即A执行完之后才执行B。以上代码中的shift是一个关键的函数,他移除并返回数组中的第一个元素,执行多次之后,这个数组最后悔变为空的,因此最终会导致错误,为了验证这个,假设这里有两个函数,我们不知道他们的执行顺序,它们都会接受一个回调函数,并在函数的末尾执行回调函数。

var A = function(callback) {
    setTimeout(function() {
        value = 10;
        callback();
    }, 200);
};
var B = function(callback) {
    console.log(value);
    callback();
};

如果按照顺序调用queue([A,B])的话,我们会得到TypeError: undefined is not a function。为了避免这种情况的发生,在next函数里面要检查funcs是否为空

var queue = function(funcs) {
    (function next() {
        if(funcs.length > 0) {
            var f = funcs.shift();
            f(next);
        }
    })();
};

下面考虑一下更多的情况,这个函数里面的this是在闭包里面的,默认是指向了全局的window对象,如果我们可以给他绑定我们自己的作用域会更好一些比如:

var queue = function(funcs, scope) {
    (function next() {
          if(funcs.length > 0) {
              var f = funcs.shift();
              f.apply(scope, [next]);
          }
    })();

我用 apply 替换了f(next)来实现设置函数的作用域以及传递next作为参数,最后一步就是考虑参数函数之间的传递,首先我们不知道传递的参数的个数,于是使用arguments变量,这个变量存在每个函数中的,是一个ArrayLike对象、里面存储了执行改函数时传递过来的参数列表,因为apply函数的第二个参数需要接受一个真的数组,来传递参数列表。可以使用Array.prototype.slice.call(arguments, 0) 搞定

var queue = function(funcs, scope) {
    (function next() {
          if(funcs.length > 0) {
              var f = funcs.shift();
              f.apply(scope, [next].concat(Array.prototype.slice.call(arguments, 0)));
          }
    })();
};

到此为止这个功能已经完全实现了让异步函数的同步执行,可以调用方式如下

    var obj = {
        value: null
    };

    queue([
        function(callback) {
            var self = this;
        setTimeout(function() {
            self.value = 10;
            callback(20);
        }, 200);
    },
    function(callback, add) {
        console.log(this.value + add);
        callback();
    },
    function() {
        console.log(obj.value);
    }
], obj);

函数的执行结果 为

30
10

言之就是把这些异步的函数放在一个数组里,然后通过next里面的shift来获取函数并传递next并实现了依次调用、最后列出queue函数的源码

var queue = function(funcs, scope) {
    (function next() {
          if(funcs.length > 0) {
              funcs.shift().apply(scope || {}, [next].concat(Array.prototype.slice.call(arguments, 0)));
          }
    })();
};

原文地址:http://krasimirtsonev.com/blog/article/7-lines-JavaScript-library-for-calling-asynchronous-functions

REST 程序设计之http method 、http status

HTTP method

在rest程序设计中对资源都是通过URI来体现的,对资源的操作主要是通过Http请求的方法来实现的。API功能是由http method+ URI共同体现的。举例如下

  • GET /tasks - 获取任务列表信息
  • GET /tasks/12 -获取指定的任务信息
  • POST /tasks - 创建新的任务
  • PUT /tasks/12 - 更新指定的任务
  • PATCH /tasks/12 - 更新指定任务的部分信息
  • DELETE /tasks/12 - 删除指定的任务

以上中get 、post、put、delete比较常用。主要实现对资源的CURD。

HTTP status

作为 API 的设计者,正确的将 API 执行结果和失败原因用清晰简洁的方式传达给客户程序是十分关键的一步。 我们确实可以在 HTTP 的相应内容中描述是否成功,如果出错是因为什么, 然而, 这就意味着用户需要进行内容解析,才知道执行结果和错误原因。因此,HTTP 响应代码可以保证客户端在第一时间用最高效的方式获知 API 运行结果,并采取相应动作。 下表列出了比较常用的响应代码。

  • 200 响应成功。主要响应GET, PUT, PATCH 、DELETE.请求,同时也可以响应资源创建成功无返回结果的post请求
  • 201 资源成功创建,同时在location header 里面有新资源的 地址
  • 204 返回请求成功 不反返回内容,即返回结果不包含body,比如delete请求。
  • 301 重定向 , 请求的网页已被永久移动到新位置。服务器返回此响应时,会自动将请求者转到新位置。
  • 302 重定向 , 请求的网页临时移动到新位置,但求者应继续使用原有位置来进行以后的请求。302 会自动将请求者转到不同的临时位置。
  • 304 自从上次请求后,请求的网页未被修改过。服务器返回此响应时,不会返回网页内容。
  • 400 错误请求
  • 401 未授权 , 请求要求进行身份验证
  • 403 已禁止 , 服务器拒绝请求。
  • 404 未找到 , 服务器找不到请求的网页。
  • 405 方法禁用 , 禁用请求中所指定的方法。
  • 410 请求的页面不存在
  • 415 不支持的媒体类型
  • 429 请求次数过多
  • 500 内部服务器错误。