首页 > 编程语言 >JS中的异步编程

JS中的异步编程

时间:2023-06-04 22:22:56浏览次数:48  
标签:异步 console log 编程 JS response data fetch

目录

前言

  fetch 是用来替代传统的XMLHttpRequest的。 fetch 的优点很多,包括链式调用的语法、返回promise等。

什么是Promise?

当在开发中需要处理异步操作时,Promise是一个常用的工具。Promise是一个表示异步操作最终完成或失败的对象。

创建一个Promise对象时,可以传入一个执行器函数,该函数接受两个参数:resolve 和 reject 。通过调用resolve函数,表示异步操作成功并传递结果,而调用reject函数表示异步操作失败并传递错误信息。

以下是一个使用Promise的简单示例:

// 创建一个简单的异步操作
const fetchData = () => {
    return new Promise((resolve, reject) => {
        // 模拟异步操作,比如从服务器获取数据
        setTimeout(() => {
            const data = {id: 1, name: 'John'};
            if (data) {
                resolve(data); // 异步操作成功
            } else {
                reject('Failed to fetch data.'); // 异步操作失败
            }
        }, 2000);
    });
};

// 使用Promise处理异步操作
fetchData()
    .then(data => {
        console.log('异步操作成功:', data);
        // 在这里可以对获取的数据进行处理
    })
    .catch(error => {
        console.log('异步操作失败:', error);
        // 在这里可以处理异步操作失败的情况
    });

  在上面的示例中,fetchData 函数返回一个 Promise 对象,通过调用 resolve 和 reject 函数来表示异步操作的结果。然后可以使用.then()来处理异步操作成功的情况,并使用.catch()来处理异步操作失败的情况。

  当异步操作成功时,.then()中的回调函数会被调用,并将异步操作的结果传递给它。当异步操作失败时,.catch()中的回调函数会被调用,并将错误信息传递给它。

  这只是Promise的基本用法,还可以使用更多的方法和技巧来处理Promise,例如使用Promise.all()来处理多个异步操作,使用async/await来编写更简洁的异步代码等。

测试示例

// 使用示例1
new Promise(function (resolve, reject) {
    var a = 0;
    var b = 1;
    if (b == 0) {
        // 触发catch块中的逻辑
        reject("除零错误");
    } else {
        // 触发then块中的逻辑
        resolve(a / b);
    }
}).then(function (value) {
    // 由resolve触发
    console.log("a / b = " + value);
}).catch(function (err) {
    // 由reject触发
    console.log(err);
}).finally(function () {
    // 无论如何要执行的语句
    console.log("最后finally块中的代码");
});

// 使用示例2
new Promise(function (resolve, reject) {
    console.log(1);
    resolve(2);
}).then(function (value) {
    console.log(value);
    return 3;
}).then(function (value) {
    console.log(value);
    throw "抛出错误";
}).catch(function (err) {
    console.log(err);
});

为什么用fetch?

fetch 官网:https://github.com/github/fetch

fetch 是 JavaScript 提供的一种现代化的网络请求 API,用于进行网络请求并获取资源。它是基于 Promise 的,使用起来相对简单和灵活。

传统的 xhr 请求写起来非常的混乱,如下所示:

例1:

var xhr = new XMLHttpRequest();
xhr.open('GET', "https://api.github.com");
xhr.responseType = 'json';

// 设置成功回调
xhr.onload = function() {
    console.log(xhr.response);
};

// 设置错误回调
xhr.onerror = function() {
    console.log("请求发生错误!");
};

// 发送请求
xhr.send();

例2:

// 需要目标站点后台服务器给响应头设置允许跨域的标识头
function sendAjax() {
    var req = new XMLHttpRequest();
    req.open('GET', "https://api.github.com");
    req.send();
    // 设置成功回调
    req.onreadystatechange = function () {
        if (req.readyState === 4) {
            try {
                alert(req.responseText);
                b = req.response;
            } catch (e) {
                alert('你访问的页面出错了');
            }
        }
    };
    // 设置请求超时回调
    req.ontimeout = function () {
        console.log("请求超时")
    }
}
sendAjax()

但使用 fetch 之后,如下所示:

fetch("https://api.github.com")
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(e => console.log("请求发生错误!"));

  在上面的示例中,使用 fetch 函数来发起一个 GET 请求,并传递目标 URL 作为参数。fetch 返回一个 Promise 对象,我们可以使用 .then() 来处理请求成功的情况,通过 .catch() 来处理请求失败的情况。

在第一个 .then() 中,我们使用 response.json() 方法将响应数据解析为 JSON 格式。这个方法也返回一个 Promise 对象,我们可以再次使用 .then() 来处理解析后的数据。

  如果需要发送 POST 请求或者设置其他请求参数,fetch 还提供了相应的选项。下面是一个带有 POST 请求和请求头设置的示例:

fetch('https://api.example.com/data', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({username: 'john', password: 'secret'})
})
    .then(response => response.json())
    .then(data => {
        console.log('获取到的数据:', data);
        // 在这里可以对获取到的数据进行处理
    })
    .catch(error => {
        console.log('请求失败:', error);
        // 在这里可以处理请求失败的情况
    });

  在上面的示例中,通过传递第二个参数来设置请求选项。method 设置为 'POST' 表示发送一个 POST 请求,headers 设置了请求头的 'Content-Type''application/json'body 是一个包含要发送的数据的对象,并使用 JSON.stringify 将其转换为 JSON 字符串。

  使用 fetch 进行网络请求的优势之一是可以与其他 JavaScript 特性(如 async/awaitPromise.all)结合使用,从而编写更简洁和灵活的代码。

async、await

asyncawait 是 JavaScript 中用于处理异步操作的关键字。它们可以用更简洁、更易读的方式编写异步代码。

async 关键字用于定义一个异步函数,异步函数内部可以包含 await 关键字。异步函数在被调用时会返回一个 Promise 对象,该对象会在异步操作完成时解析为返回值。

下面是一个简单的示例,展示了如何使用 asyncawait

// 异步函数
async function fetchData() {
    // 模拟异步操作,比如从服务器获取数据
    const response = await fetch('https://api.github.com/users/mzabriskie');
    const data = await response.json();
    return data;
}

// 使用异步函数
async function processData() {
    try {
        const result = await fetchData();
        console.log('异步操作成功:', result);
        // 在这里可以对获取的数据进行处理
    } catch (error) {
        console.log('异步操作失败:', error);
        // 在这里可以处理异步操作失败的情况
    }
}

// 调用异步函数
processData();

  在上面的示例中,fetchData 是一个异步函数,内部使用了 await 关键字来等待异步操作的结果。fetch 函数返回一个 Promise 对象,使用 await 等待该 Promise 对象解析为结果。类似地,response.json() 也返回一个 Promise 对象,也需要使用 await 等待结果。

  在 processData 函数中,我们使用 try...catch 来捕获可能发生的错误。如果异步操作成功,await 表达式会返回异步操作的结果,并将其赋值给 result 变量。如果异步操作失败,会抛出一个错误,被 catch 块捕获并进行处理。

  总结一下,async 关键字用于定义异步函数,await 关键字用于等待异步操作的结果。它们的使用可以让异步代码更加清晰、易读,并且可以使用类似同步代码的方式进行编写。

  • 异步执行验证:最后打印的时间相差在1秒内即为异步执行
async function test() {
    let b = 0;
    for (let i = 0; i < 100000000; i++) {
        b++;
    }
    console.log(b)
    console.log(new Date())
}

for (var i = 0; i < 10; i++) {
    test()
}
  • 异步请求示例
// async function
async function fetchAsync() {
    // await response of fetch call
    let response = await fetch('https://api.github.com');
    // only proceed once promise is resolved
    let data = await response.json();
    // only proceed once second promise is resolved
    return data;
}

// trigger async function
// log response or catch error of fetch promise
fetchAsync()
    .then(data => console.log(data))
    .catch(e => console.log(e.message))

基本使用方法

fetch 必须接受一个资源路径作为参数,并且返回了一个promise,所以我们可以直接使用链式调用的方式。

ajax请求

fetch("/getAllUserInfo")
    .then(res => res.json())
    .then(data => {
        if (data.code === 200) {
            console.log('获取所有用户信息', data.data);
            // 其它业务逻辑
        } else {
            console.log(data.message);
        }
    })

自定义请求

fetch 提供了对 Request 和 Response (以及其他与网络请求有关的)对象的通用定义。所以在一个Fetch请求中,完全可以只使用Request 和 Response两个对象,通过Request 设置参数,通过Response 对返回值进行处理。

var myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');

var option = {
    method: 'GET',
    headers: myHeaders,
    mode: 'cors',
    cache: 'default'
};

var myRequest = new Request('https://api.github.com/users/mzabriskie', option);
fetch(myRequest).then(response => {
    console.log(response)
    return response.json()
}).then(data => console.log(data));

HTML请求

fetch('/users.html')
  .then(function(response) {
    return response.text()
  }).then(function(body) {
    document.body.innerHTML = body
  })

JSON请求

fetch('/users.json')
  .then(function(response) {
    return response.json()
  }).then(function(json) {
    console.log('parsed json', json)
  }).catch(function(ex) {
    console.log('parsing failed', ex)
  })

Response metadata

fetch('/users.json').then(function(response) {
  console.log(response.headers.get('Content-Type'))
  console.log(response.headers.get('Date'))
  console.log(response.status)
  console.log(response.statusText)
})

Post form

var form = document.querySelector('form')
fetch('/users', {
  method: 'POST',
  body: new FormData(form)
})

Post JSON

fetch('/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Hubot',
    login: 'hubot',
  })
})

File upload

var input = document.querySelector('input[type="file"]')

var data = new FormData()
data.append('file', input.files[0])
data.append('user', 'hubot')

fetch('/avatars', {
  method: 'POST',
  body: data
})

注意点

1、 fetch api 提供的spi囊括但是不限于xhr的所有功能。

2、 fetch api 可以跨域,参考: https://fetch.spec.whatwg.org/#http-cors-protocol

要求响应对象的header中必须含有Access-Control-Allow-origin允许跨域的标识

img

在发送 fetch 请求的时候就会使用到CORS协议,尽管这些对于开发者来说是透明的,但是浏览器还是会发送 origin 字段。

标签:异步,console,log,编程,JS,response,data,fetch
From: https://www.cnblogs.com/hhddd-1024/p/17456520.html

相关文章

  • threejs绘制多边形几何体
    threejs绘制多边形 //创建一个立方体几何体varcubeGeometry=newTHREE.BoxGeometry(0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5);//创建一个多边形几何体varpolygonGeometry=newTHREE.Geometry();//创建多边形的顶点数......
  • 面向对象编程三大特性
    封装:通俗来说就是类(class),将数据变量和函数方法封装到一起成为类,实其可以被创建对象 继承:子类可以继承父类的变量和方法并以此基础进行拓展 多态:通过虚函数、基类指针或引用调用适当的子类的函数版本,实现统一函数名多个功能......
  • Js中var,let,const的区别总结
    目录区别var关键字let关键字const关键字区分var和let声明变量(作用域区别)var声明let声明因为let和const是es6的新特性,let和const的出现就是为了解决var的各种问题,因此在声明变量时能不用var就不用,强烈建议都用let和const声明变量和常量!区别1、var声明的变......
  • 实验5 文件应用编程
    实验任务6源代码1withopen('data6.csv','r',encoding='gbk')asf:2data=list(f.readlines())3data=[i.strip('\n')foriindata]45importdecimal6decimal.getcontext().rounding='ROUND_HALF_UP'......
  • 异步执行
    异步执行远程查询库存@FeignClient("gulimall-ware")publicinterfaceWmFeignService{//查询是否有库存@PostMapping("ware/waresku/hasstock")//ware/wareskupublicRgetSkusHassStock(@RequestBodyList<Long>skuIds);}gulimall-ware中注......
  • 在nodejs addon 环境下抓视频和音频数据包
    在nodeaddon环境下开发音视频,需要用到gyp。这个配置比较简单,很快可以配置好。比较坑的是,在vscode开发环境下,如果装了conda或者miniconda.有可能会影响gpy程序的编译。谨慎起见,可以看看控制台是否有(condabase)环境启动,可以想办法先脱离conda环境。废话不说直接......
  • NOI / 1.9编程基础之顺序查找
    4:谁拿了最多奖学金描述某校的惯例是在每学期的期末考试之后发放奖学金。发放的奖学金共有五种,获取的条件各自不同:1)    院士奖学金,每人8000元,期末平均成绩高于80分(>80),并且在本学期内发表1篇或1篇以上论文的学生均可获得;2)    五四奖学金,每人4000元,期末平均成绩高于......
  • NOI / 1.9编程基础之顺序 04:谁拿了最多奖学金
    描述某校的惯例是在每学期的期末考试之后发放奖学金。发放的奖学金共有五种,获取的条件各自不同:院士奖学金,每人8000元,期末平均成绩高于80分(>80),并且在本学期内发表1篇或1篇以上论文的学生均可获得;五四奖学金,每人4000元,期末平均成绩高于85分(>85),并且班级评议成绩高于80分(>80)的......
  • js数组对象转树结构
    原始数组对象:letarr=[{id:1,name:"节点1",parentId:0},{id:2,name:"节点2",parentId:1},{id:3,name:"节点3",parentId:1},{id:4,name:"节点4",parentId:2},{id:5,name:"节点5&qu......
  • 高并发下的Node.js与负载均衡
     新兴的Node.js已经吸引了很多开发人员的眼光,它提供给我们一个快速构建高性能的网络应用的平台。我也开始逐步投入node.js的怀抱,在学习和使用的过程中,遇到了一些问题,也有一些经验,我觉得有必要写出来,作为总结,也用作分享。众所周知,node.js基于v8引擎,所以它本身并不支持多线程(有多线......