当前位置: 代码迷 >> 综合 >> 异步编程——回调函数/Promise/Async/Await
  详细解决方案

异步编程——回调函数/Promise/Async/Await

热度:112   发布时间:2023-11-11 01:44:00.0

感觉自己在异步编程这一块掌握的还是不很好,然后决定今天开始认认真真学习一下这一块的知识点,一定要学会!!

最基本的回调函数的使用

1.1 回调函数加载图片

let loadImage = function(src,callback){
    var img = new Image();img.src = src;img.onload = ()=>{
    callback(img);};img.onerror = ()=>{
    console.log("加载失败");}
} 
let imageloadCallback = function(img){
    document.body.appendChild(img);console.log("图片加载完成~");
}
loadImage("**",imageloadCallback);

1.2 定时器

let interval = function(callback,time=50){
    let tag = setTimeInterval(callback,time);
}

1.3 回调地狱的产生:以加载文件为例
假设下列文件是有相互依赖的关系的话,就会产生层层的叠加=>回调地狱

let loadJs = function(src,callback){
    let script = document.createElement("script");script.src = src;document.body.appendChild(script);script.onload = callback;
}loadJs("1.js",()=>{
    console.log("1.js加载完成了");loadJS("2.js",()=>{
    console.log("2.js加载完成了");loadJS("3.js",()=>{
    console.log("3.js加载完成了");})})
})

Promise的使用

2.1 基本使用方法

new Promise((res,rej)=>{
    res("value");// rej(new Erro("reason"));
}).then((value)=>{
    console.log(value);
}).catch((reason)=>{
    console.log(reason);
});

2.2 代码的同步和异步执行顺序
主线程代码(同步代码)->(微任务 & 宏任务)
以下是非常典型的两个例子:

	console.log("主线程开始");let pro1 = new Promise((res,rej)=>{
    console.log("同步任务");setTimeout(()=>{
    console.log("宏任务")res();},0);}).then(()=>{
    console.log('微任务回调');});console.log("主线程结束");//输出顺序 主线程开始 同步任务 主线程结束 红任务 微任务
	setTimeout(()=>{
    console.log("宏任务")},0);console.log("主线程开始");let pro1 = new Promise((res,rej)=>{
    console.log("同步任务");res();}).then(()=>{
    console.log('微任务回调');});console.log("主线程结束")//输出顺序 主线程开始 同步任务 主线程结束 微任务回调 宏任务

根据?两个例子可以知道,微任务并不是总是优先于红任务执行的,这主要是要根据判断微任务队列中是否有任务,第一个例子中因为微任务的产生依靠宏任务,所以出现了这样的结果。

2.2 单一状态和状态中转
在学习promise的过程中,这边出现了问题(等到后期修改解决一下)

var pro1 = new Promise((res,rej)=>{
    rej(new Error("somethinr wrong with promise1"));
})
var pro2 = new Promise((res,rej)=>{
    res(pro1);
})
pro2.then(()=>{
    console.log("成功")}).catch(()=>{
    console.log("失败")});
//结果是 失败

从这个例子可以看出这个pro2的状态完全依赖于pro1的状态,哪怕pro2中调用了resolve回调。
but~!

var pro1 = new Promise((res,rej)=>{
    rej(new Error("somethinr wrong with promise1"));
}).then(()=>{
    console.log("成功")}).catch(()=>{
    console.log("失败")});
var pro2 = new Promise((res,rej)=>{
    res(pro1);
})
pro2.then(()=>{
    console.log("成功")}).catch(()=>{
    console.log("失败")});
//结果是 失败 成功

暂时不是很理解为什么这里pro2的状态是成功~

2021.1.25 更新:因为pro1的状态已经确定了所以pro2的res调用其实就是简单的把pro1这个确定的对象传给了成功回调函数;而当pro1的状态还没有确定的时候,对于pro2的状态决定于pro1!

2.3 使用promise修改并对比回调函数加载图片的方法

let loadImage = function(src){
    return new Promise((res,rej)=>{
    let img = new Image();img.src = src;img.onload = ()=>{
    res(img);}img.onerror = ()=>{
    rej("加载失败");}})
}
loadImage('**').then((img)=>{
    document.body.append(img);
})

Promise链式调用的结论

let p1 = new Promise((res,rej)=>{
    res("成功");
});
p1.then(()=>{
    return {
    then(res,rej){
    rej('链式调用的时候的错误');}};
}).catch(value=>{
    
console.log(value)});

手写promise

//-------------------------------------------class GCPromise{
    constructor(excutor){
    this.resolveList = [];this.rejectList = [];this.value = undefined;this.reason = undefined;let resolve = (input)=>{
    this.value = input;while(this.resolveList.length!==0){
    let fun = this.resolveList.shift();fun(this.value);}}let reject = (input)=>{
    this.reason = input;while(this.rejectList.length!==0){
    let fun = this.rejectList.shift();fun(input);}}excutor(resolve,reject);}then(onResolved,onrejected){
    this.rejectList.push(onrejected);this.resolveList.push(onResolved);}}var p1 = new GCPromise((res,rej)=>{
    setTimeout(()=>{
    rej("sorry");},1000);}).then((res)=>{
    console.log(res);},(reason)=>{
    console.log(reason);});;//----------------------------------------------const PENDING = 'pending';const RESOLVE = 'fullfilled';const REJECT = 'rejected';class MyPromise{
    constructor(executor){
    this.resolveList = [];this.rejectList = [];this.status = PENDING;this.value = undefined;this.reason = undefined;let resolve = (val)=>{
    if(this.status!==PENDING) return;this.status = RESOLVE;this.value = val;while(this.resolveList.length){
    let fun = this.resolveList.shift();fun(this.value);}}let reject = (val)=>{
    if(this.status!==PENDING) return;this.status = REJECT;this.reason = val;while(this.rejectList.length){
    let fun = this.rejectList.shift();fun(this.reason);}}executor(resolve,reject);}then(onresolved,onrejected){
    onresolved = typeof onresolved === 'function'? onresolved: value=>value;onrejected = typeof onrejected === 'function'? onrejected: value=>value;return new MyPromise((res,rej)=>{
    let resolve = value=>{
    try {
    const x = onresolved(value);x instanceof MyPromise? x.then(res,rej):res(x);}catch(e){
    rej(e);}}let reject = value=>{
    try {
    const x = onrejected(value);x instanceof MyPromise? x.then(res,rej):rej(x);}catch(e){
    rej(e);}}if(this.status === PENDING){
    this.resolveList.push(resolve);this.rejectList.push(reject);}else if(this.status === RESOLVE){
    resolve(this.value);}else if(this.status === REJECT){
    resolve(this.reason);}})}}new MyPromise((res,rej)=>{
    setTimeout(()=>{
    res(1);},1000);}).then((value)=>{
    console.log(value);return 1;}).then((value)=>{
    console.log(value);return 2;}).then((value)=>{
    console.log(value);})

promise队列实现

5.1 map实现promise队列

let query = function(numList){
    let promise1 = Promise.resolve();numList.map(x=>{
    promise1 = promise1.then(value=>{
    return new Promise((res,rej)=>{
    setTimeout(()=>{
    res(x);console.log(x);},1000);});})})}query([1,2,3,4,5]);
let queue = function(numList){
    let promise1 = Promise.resolve();numList.map(x=>{
    promise1 = promise1.then(value=>{
    return x();})})}query([p1,p2,p3,p4]);

async await

这算是promise和generator的语法糖,写起来比较容易
使用方法有以下几种
1.

function yibu(){
    return new Promise((res,rej)=>{
    ...res();//...rej();})
}
async function tongbu(){
    let response = await yibu();return response;
}
tongbu().then((value)=>{
    
})...
class yibu{
    constructor(name){
    this.name = name;}then(res,rej){
    res(this.name);}
}
async function tongbu(){
    let response = await new yibu("gucheng");return response;
}
tongbu().then((value)=>{
    
})...
function yibu1(){
    return new Promise((res,rej)=>{
    setTimeout(()=>{
    resolve("yibu1");},1000);})
}
function yibu2(){
    return new Promise((res,rej)=>{
    setTimeout(()=>{
    resolve("yibu2");},1000);})
}
async function tonbu(){
    let res1 = await yibu1();let res2 = await yibu2();
}
  相关解决方案