资讯专栏INFORMATION COLUMN

FE.ES-异步编程进化史

Aceyclee / 822人阅读

摘要:本文通过实践从古至今对封装的各种方式,来了解在中异步编程的实现细节和设计模式。传值方式实现传对象方式实现基于其他实现当前是第次等待感觉是到来之前的过渡方案异步流程控制库中文文档参考使用深入理解的中文文档

本文通过实践从古至今对XMLHttpRequest封装的各种方式,来了解在es中异步编程的实现细节和设计模式。

回顾XMLHttpRequest原生写法

XMLHttpRequest -MDN

var xhr = new XMLHttpRequest()
xhr.timeout = 2000
xhr.open("POST", "path/to/api")
xhr.onload= function () {console.log(xhr.status,xhr.responseText)}
xhr.setRequestHeader("Content-type","text/plain;charset=UTF-8")
xhr.send("{"key":"value"}")
常见封装方法 1.回调函数

传值方式实现

function request(method, url, done) {
  var xhr = new XMLHttpRequest()
  xhr.open(method, url)
  xhr.onload = function () {
    if (this.status >= 200 && this.status < 300)
        done(null, xhr.response)
    else
        done(xhr.response)
  }
  xhr.onerror = function () {done(xhr.response)}
  xhr.send()
}
//---
request("GET", "path/to/api", function (err, res) {
  if (err){console.error(err)}
  console.log(res)
})

传对象方式实现

function request(obj){
    var xhr = new XMLHttpRequest()
    xhr.open(obj.method, obj.url)
    xhr.onload= function () {
        if (this.status >= 200 && this.status < 300)
            obj.success(xhr.response)
        else
            obj.fail(xhr.response)
    }
    xhr.onerror= function () {obj.fail(xhr.response)}
    for(let key in obj.header){xhr.setRequestHeader(key ,obj.header[key])}
    xhr.send(obj.data)
}
//---
request({
    url: "path/to/api",
    data: {},
    method:"GET",
    header: {"Content-type": "application/json"},
    success(res) {console.log(res)},
    fail(err) {console.error(err)}
})
2.Promise

使用 Promise - MDN
Promise 本质上是一个绑定了回调的对象,而不是将回调传进函数内部。
传值方式实现

function requestPromise(method, url) {
  return new Promise(function (resolve, reject) {
    var xhr = new XMLHttpRequest()
    xhr.open(method, url)
    xhr.onload = function () {
      if (this.status >= 200 && this.status < 300)
        resolve(xhr.response)
      else
        reject({status: this.status,statusText: xhr.statusText})
    }
    xhr.onerror = function () {
      reject({status: this.status,statusText: xhr.statusText})
    }
    xhr.send()
  })
}
// ---
requestPromise("GET", "path/to/api")
.then(function (res1) {
  return makeRequest("GET", res1.url)
})
.then(function (res2) {
  console.log(res2)
})
.catch(function (err) {
  console.error(err)
});

传对象方式实现

function makeRequest (opts) {
  return new Promise(function (resolve, reject) {
    var xhr = new XMLHttpRequest();
    xhr.open(opts.method, opts.url);
    xhr.onload = function () {
      if (this.status >= 200 && this.status < 300) {
        resolve(xhr.response);
      } else {
        reject({
          status: this.status,
          statusText: xhr.statusText
        });
      }
    };
    xhr.onerror = function () {
      reject({
        status: this.status,
        statusText: xhr.statusText
      });
    };
    if (opts.headers) {
      Object.keys(opts.headers).forEach(function (key) {
        xhr.setRequestHeader(key, opts.headers[key]);
      });
    }
    var params = opts.params;
    // We"ll need to stringify if we"ve been given an object
    // If we have a string, this is skipped.
    if (params && typeof params === "object") {
      params = Object.keys(params).map(function (key) {
        return encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
      }).join("&");
    }
    xhr.send(params);
  });
}

// Headers and params are optional
makeRequest({
  method: "GET",
  url: "http://example.com"
})
.then(function (datums) {
  return makeRequest({
    method: "POST",
    url: datums.url,
    params: {
      score: 9001
    },
    headers: {
      "X-Subliminal-Message": "Upvote-this-answer"
    }
  });
})
.catch(function (err) {
  console.error("Augh, there was an error!", err.statusText);
});
3.fetch ,Request (基于promise)

fetch-MDN

fetch("path/to/api", {credentials: "include"})
.then(function(response) {
    if (response.status >= 400) {
        throw new Error("Bad response from server");
    }
    return response.json();
})
.then(function(stories) {
    console.log(stories);
});

Request-MDN

var myRequest = new Request(
                    "path/to/api", 
                    { method: "GET",
                       headers: {"Content-Type": "application/json"},
                       mode: "cors",
                       cache: "default" 
                   }
               )
fetch(myRequest).then(function(response) {
  //...
});
4.async/await (ES7)

async function -MDN
await -MDN

async function f1() {
  var res = await requestPromise("GET", "path/to/api");
  console.log(res)
}
f1();
其他 sleep 实现 (async/await)
function sleep (time) {
    return new Promise(function (resolve, reject) {setTimeout(resolve, time)})
}

var start = async function () {
    for (var i = 1; i <= 10; i++) {
        console.log(`当前是第${i}次等待..`);
        await sleep(1000);
    }
};

start();
co+Generator

感觉是 async/await 到来之前的过渡方案

const co=require("co")
//let begin = new Date();
co(function* (){
    let buyed = yield buySomething();
    //console.log(buyed ,new Date() - begin);
    
    let cleaned = yield clean();
    //console.log(cleaned ,new Date() - begin);
    
    let cook_and_wash = yield [cook(),wash()];
    //console.log(cook_and_wash ,new Date() - begin);
    
    let eated = yield eat();
    //console.log(eated,new Date() - begin);
});
异步流程控制库

RxJS 中文文档

参考
XMLHttpRequest -MDN
使用 Promise - MDN
How do I promisify native XHR? - starkoverflow
深入理解ES7的async/await
fetch-MDN
Request-MDN
async function -MDN
await -MDN
RxJS 中文文档
Promises/A+

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/117089.html

相关文章

  • FE.ES-异步编程化史

    摘要:本文通过实践从古至今对封装的各种方式,来了解在中异步编程的实现细节和设计模式。传值方式实现传对象方式实现基于其他实现当前是第次等待感觉是到来之前的过渡方案异步流程控制库中文文档参考使用深入理解的中文文档 本文通过实践从古至今对XMLHttpRequest封装的各种方式,来了解在es中异步编程的实现细节和设计模式。 回顾XMLHttpRequest原生写法 XMLHttpRequest ...

    yeyan1996 评论0 收藏0
  • FE.ES-异步编程化史

    摘要:本文通过实践从古至今对封装的各种方式,来了解在中异步编程的实现细节和设计模式。传值方式实现传对象方式实现基于其他实现当前是第次等待感觉是到来之前的过渡方案异步流程控制库中文文档参考使用深入理解的中文文档 本文通过实践从古至今对XMLHttpRequest封装的各种方式,来了解在es中异步编程的实现细节和设计模式。 回顾XMLHttpRequest原生写法 XMLHttpRequest ...

    1fe1se 评论0 收藏0
  • 半理解系列--Promise的化史

    摘要:异步编程一般用来调取接口拉数据。通过我描述的篇幅,就知道异步编程比同步编程麻烦许多。远古时期,异步编程是通过回调函数来解决的。 半理解系列--Promise的进化史 学过js的都知道,程序有同步编程和异步编程之分,同步就好比流水线,一步一个脚印,做完上个任务才做下一个,异步编程好比客服,客服接了一个电话,收到了一个任务,然后把任务交给另外的人来处理,同时,继续接听下一个电话,等到另外的...

    Eminjannn 评论0 收藏0
  • FE.ES-JavaScript的模块化历史

    摘要:模块化之前的污染,命名污染命名空间模式减少上变量数量,但仍不安全匿名闭包模式应用由模块组成,采用模块规范。要想让模块再次运行,必须清除缓存。中优先于模块内的其他内容执行。与其对应的值是动态绑定关系,实时取到模块内部的值。 模块化之前的JavaScript //Global污染,命名污染 function foo(){} //命名空间 NameSpace模式 var Module= { ...

    caoym 评论0 收藏0
  • JS 异步编程六种方案

    摘要:接下来介绍下异步编程六种方法。六生成器函数是提供的一种异步编程解决方案,语法行为与传统函数完全不同,最大的特点就是可以控制函数的执行。参考文章前端面试之道异步编程的种方法你不知道的中卷函数的含义和用法替代的个理由 前言 我们知道Javascript语言的执行环境是单线程。也就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务。 这种模式虽然实现起...

    longmon 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<