JavaScript异步操作

JavaScript异步操作

promise

js单线程
https://blog.csdn.net/qq_40099141/article/details/83991213

回调

1
2
3
4
5
6
function callback() {
console.log('Done');
}
console.log('before setTimeout()');
setTimeout(callback, 1000); // 1秒钟后调用callback函数
console.log('after setTimeout()');

最简单的promise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
定义函数
function test1(resolve, reject) {
var timeOut = Math.random() * 2;
console.log('set timeout to: ' + timeOut + ' seconds.');
setTimeout(function () {
if (timeOut < 1) {
console.log('call resolve()...');
resolve('200 OK');
}
else {
console.log('call reject()...');
reject('timeout in ' + timeOut + ' seconds.');
}
}, timeOut * 1000);
}

调用函数

1
test(function(mes){console.log(mes);},function(mes){console.log(mes);})

这个test()函数有两个参数,这两个参数都是函数,如果执行成功,我们将调用resolve(‘200 OK’),如果执行失败,我们将调用reject(‘timeout in ‘ + timeOut + ‘ seconds.’)。可以看出,test()函数只关心自身的逻辑,并不关心具体的resolve和reject将如何处理结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var p1 = new Promise(test);
var p2 = p1.then(function (result) {
console.log('成功:' + result);
});
var p3 = p2.catch(function (reason) {
console.log('失败:' + reason);
});

第二种调用方式
var p1 = new Promise(test1(mes=>console.log(mes+'===='),mes=>console.log(mes+'---')));
var p2 = p1.then(function (result) {
console.log('成功:' + result);
});
var p3 = p2.catch(function (reason) {
console.log('失败:' + reason);
});

第二种调用方式会报错:
这里您尝试在创建Promise实例时,直接传入test1函数执行的结果(即带有参数的函数调用)。然而,new Promise()期望接收的是一个executor函数作为参数,而不是一个已经执行并返回结果的表达式。
当您这样写时,JavaScript引擎会立即尝试执行test1函数,并将传递给它的两个回调函数分别作为参数,但test1函数内部并没有定义处理这两个回调函数的方式。实际上,test1应该是在Promise构造器内部被调用,并由引擎传入resolve和reject函数作为参数。

new Promise(test).then(job2).then(job3).catch(handleError);

catch捕获的是job2,job3中所有的错误

async

我们说JavaScript异步操作需要通过Promise实现,一个Promise对象在操作网络时是异步的,等到返回后再调用回调函数,执行正确就调用then(),执行错误就调用catch(),虽然异步实现了,但是一堆then()catch()写起来麻烦看起来也乱。

有没有更简单的写法?

在普通function中调用async function,不能使用await(会报错),但可以直接调用async function拿到Promise对象,后面加上then()和catch()就可以拿到结果或错误了。
await调用必须在async function中,不能在传统的同步代码中调用。

可以用关键字async配合await调用Promise,实现异步操作,但代码却和同步写法类似:

fetch 的返回值是Promise

1
2
3
4
async function get(url) {
let resp = await fetch(url);
return resp.json();
}

使用async function可以定义一个异步函数,异步函数和Promise可以看作是等价的,在async function内部,用await调用另一个异步函数,写起来和同步代码没啥区别,但执行起来是异步的。

也就是说:

1
let resp = await fetch(url);

自动实现了异步调用,它和下面的Promise代码等价:

1
2
3
4
let promise = fetch(url);
promise.then((resp) => {
// 拿到resp
})

如果我们要实现catch()怎么办?用Promise的写法如下:

1
2
3
4
5
6
let promise = fetch(url);
promise.then((resp) => {
// 拿到resp
}).catch(e => {
// 出错了
});

await调用时,直接用传统的try{ ... } catch

1
2
3
4
5
6
7
8
async function get(url) {
try {
let resp = await fetch(url);
return resp.json();
} catch (e) {
// 出错了
}
}

用async定义异步函数,用await调用异步函数,写起来和同步代码差不多,但可读性大大提高。

需要特别注意的是,await调用必须在async function中,不能在传统的同步代码中调用。那么问题来了,一个同步function怎么调用async function呢?

首先,普通function直接用await调用异步函数将报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
'use strict';
async function get(url) {
let resp = await fetch(url);
return resp.json();
}

function doGet() {
let data = await get('/api/categories');
console.log(data);
}

doGet();

SyntaxError: await is only valid in async functions and the top level bodies of modules

如果把await去掉,调用实际上发生了,但我们拿不到结果,因为我们拿到的并不是异步结果,而是一个Promise对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
'use strict';
async function get(url) {
let resp = await fetch(url);
return resp.json();
}

function doGet() {
let promise = get('/api/categories');
console.log(promise+"2");
}

doGet();

[object Promise]2

因此,在普通function中调用async function,不能使用await,但可以直接调用async function拿到Promise对象,后面加上then()catch()就可以拿到结果或错误了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'use strict';
async function get(url) {
let resp = await fetch(url);
return resp.json();
}

function doGet() {
let promise = get('/api/categories');
promise.then(data => {
// 拿到data
document.getElementById('test-response-text').value = JSON.stringify(data);
});
}

doGet();

因此,定义异步任务时,使用async function比Promise简单,调用异步任务时,使用await比Promise简单,捕获错误时,按传统的try...catch写法,也比Promise简单。只要浏览器支持,完全可以用async简洁地实现异步操作。

let ss = await asyncGetStorage(‘ddd’); asyncGetStorage返回了一个Promise对象,为什么ss不是一个Promise对象?

1
2
3
4
5
6
7
8
9
10
11
12
在JavaScript中,await 关键字用于等待Promise对象解析,并获取其结果。当它前缀在一个Promise表达式上时,会暂停后面代码的执行,直到Promise完成(resolve)并返回Promise的结果。

1. `asyncGetStorage('ddd')` 是一个返回Promise的异步函数调用。

2. 当你在 `async` 函数内部使用 `await` 关键字来等待这个Promise时(假设该代码处于一个异步函数上下文中,因为只有在异步函数中才能正确使用 `await`),如:

3.async function someFunction() {
let ss = await asyncGetStorage('ddd');
}


4. 在这种情况下,`ss` 不是一个Promise对象,而是Promise解析后的实际值。这是因为 `await` 会等待Promise解决,并将Promise的结果赋值给变量 `ss`。

网络请求

fetch(“https://jsonplaceholder.typicode.com/users“)
.then((res) => res.json())
.then((data) => console.log(data));


参考链接:

Fetch、Axios、Ajax 的理解

https://blog.csdn.net/qq_64655972/article/details/134112133

下一代ajax技术 fetch api
https://blog.csdn.net/ZHANGYANG_1109/article/details/127996511