同步和异步

1、同步
var a=3;
var b=4;
console.log(b);
var c=a+b;
console.log(c);
for(var i=0;i<10000;i++){
    c+=i;
}
console.log(c);

// 同步
function fn1(fn){
    console.log("a");
    fn();
}
function fn2(){
    console.log("b");
}
fn1(fn2);

// 同步
console.log("a");
document.addEventListener("abc",abcHandler);
console.log("b");
var evt=new Event("abc");
document.dispatchEvent(evt);
console.log("d");
function abcHandler(e){
    console.log("c");
}

// 同步
var sum=0;
for(var i=0;i<100000000;i++){
    sum+=i;
}
console.log(sum);
console.log("b");

异步

console.log("a");
setTimeout(function(){
    console.log("b");
},1000)
console.log("c");
事件 load、error、setTimeOut、setInterval、Promise都是异步
// 加载就是异步的过程
console.log("a");
var img=new Image();
img.addEventListener("load",loadHandler);
img.src="./img/3-.jpg";
console.log("c");

function loadHandler(e){
    console.log("b");
}
// a、c、b
async、defer
// 如果直接加载js文件,首先加载第一个文件,并且执行这个js所有代码,完成后再加载b.js,然后再执行b中的代码
// 这种情况叫做同步
<script src="./js/a.js" async></script>
<script src="./js/b.js" defer></script>

// async异步的意思
// defer 延迟最后执行
Promise是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法
1、Promise是一个构造函数,所以可以 new 出一个Promise的实例

2、在Promise上有两个函数 resolve(成功之后的回调函数)reject(失败后的回调函数)

3、在Promise构造函数的prototype属性上,有一个 .then() 方法。所以只要是Promise构造函数创建的实例,都可以访问到 .then()方法

4、Promise表示一个一步操作,每当我们new一个Promise的实例,这个实例就代表具体的异步操作。

5、Promise创建的实例,是一个异步操作,这个异步操作结果,只有两种结果

1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列

// new 出一个Promise的实例
// function内部写的就是具体的异步操作
var p=new Promise(function(a,b){
    // a和b是两个回调函数
    var i=2;
    if(i>2){
        a();
    }else{
        b();
    }
});
// 在Promise构造函数的prototype属性上,有一个 .then() 方法。
// 所以只要是Promise构造函数创建的实例,都可以访问到 .then()方法
p.then(function(){
    console.log("aaa");
},function(){
    console.log("bbb");
});
// 打印结果bbb



    var p=new Promise(fn);
    p.then(fn1,fn2);

    function fn1(){
        console.log("aaa");
    }
    function fn2(){
        console.log("bbb");
    }

    function fn(a,b){
        var i=2;
        if(i<2){
            a();
        }else{
            b();
        }
    }
标准写法
var  p=new Promise(function(resolve,reject){
    var i=3;
    if(i>2){
        resolve();
    }else{
        reject();
    }
})
p.then(function(){

},function(){
         
})
// 在这里就体现了Promise是一个异步的过程
console.log("a");
var p=new Promise(function(resolve,reject){
    console.log("b");
    resolve();
})
console.log("c");
p.then(function(){
    console.log("d");
},function(){

})
console.log("e");
// 执行结果a、b、c、e、d
function loadImage(src){
    var p=new Promise(function(resolve,reject){
        var img=new Image();
        // resolve 是表示正确完成时执行的函数
        img.onload=function(){
            resolve(img);
        }
        // reject 是表示错误时执行的函数
        img.onerror=function(){
            reject(src);
        }
        img.src=src;
    });
    return p;
}

var p=loadImage("./img/a.jpg");
var s=p.then(function(img){
    console.log(img.width);
    // 如果在这里没有使用return,返回其它内容,会自动返回一个空的Promise
},function(src){
    console.log(scr+"加载失败");
})
s.then(function(img){
    console.log("abcd",img);
},function(){

})
function loadImage(src){
    var p=new Promise(function(resolve,reject){
        var img=new Image();
        // resolve 是表示正确完成时执行的函数
        img.onload=function(){
            resolve(img);
        }
        // reject 是表示正确完成时执行的函数
        img.onerror=function(){
            reject(src);
        }
        img.src=src;
    });
    return p;
}

// 这里利用return返回,连续加载
var s=loadImage("./img/3-.jpg").then(function(img){
    console.log(img.width,img.src);
    return loadImage("./img/4-.jpg");
});
s.then(function(img){
    console.log(img.width,img.src);
})


// 连缀式写法
loadImage("./img/3-.jpg").then(function(img){
    console.log(img.width,img.src);
    return loadImage("./img/4-.jpg");
}).then(function(img){
    console.log(img.width,img.src);
    return loadImage("./img/5-.jpg");
}).then(function(img){
    console.log(img.width,img.src);
    return loadImage("./img/6-.jpg");
}).then(function(img){
    console.log(img.width,img.src);
    return loadImage("./img/7-.jpg");
}).then(function(img){
    console.log(img.width,img.src);
})
function loadImage(src){
    var p=new Promise(function(resolve,reject){
        var img=new Image();
        // resolve 是表示正确完成时执行的函数
        img.onload=function(){
            // resolve(img);就是回调函数
            // 将数据传入给then的第一个函数
            resolve(img);
        }
        // reject 是表示错误时执行的函数
        img.onerror=function(){
            reject(src);
        }
        // 赋值路径地址
        img.src=src;
    });
    return p;
}

// 直接执行Promise的resolve方法,并且传入参数
Promise.resolve(3).then(function(num){
    console.log(num);
});


var p=new Promise(function(resolve,reject){
    resolve(3);
});
p.then(function(num){
    console.log(num);
});



Promise中状态只能被执行一次
在Promise中resolve和reject,只能被调用一次,不能同时调用
在Promise中有一个状态,就是准备状态pending
var p=new Promise(function(resolve,reject){
    // 当执行resolve或者reject时,这个Promise当中状态就会被修改
    // 如果当前不是准备状态时,就不会执行resolve或者reject
    resolve(4);// 当执行resolve后,状态会变为resolved状态
    reject(4);// 当执行reject后,状态会变为rejected状态  
});
// then中的第一个函数,是promise里面执行了resolve方法执行的
// catch中的函数,是promise里面执行reject方法执行的
p.then(function(num){
    console.log(num);
}).catch(function(num){
    console.log(num);
})

// 上下两种写法相同

// catch中的函数,是promise里面执行reject方法执行的
Promise.reject(4).catch(function(num){
    console.log(num);
});
var p=new Promise(function(resolve,reject){
    reject(4);
});
p.then(function(){
         
},function(num){
    console.log(num);
})
预加载
1// 将每次循环"./img/"+i+"-.jpg"作为参数带入
function loadImage(src){
    var p=new Promise(function(resolve,reject){
        var img=new Image();
        // resolve 是表示正确完成时执行的函数
        img.onload=function(){
            // resolve(img);就是回调函数
            // 将数据传入给then的第一个函数
            resolve(img);
        }
        // reject 是表示正确完成时执行的函数
        img.onerror=function(){
            reject(src);
        }
        // 赋值路径地址
        img.src=src;
    });
    return p;
}

var arr=[];
for(var i=3;i<80;i++){
    // 每执行一个loadImage函数,创建出每一个Promise
    // 按照顺序全部加载
    var p=loadImage("./img/"+i+"-.jpg");
    // 将创建的每一个Promise放入到数组里
    arr.push(p);
}

// Promise.all()
// 将Promise对象数组按照顺序异步全部完成后再then的第一个函数中,传入完成结果
// 在这里then方法接受成功时的回调函数
// list表示的是异步执行成功之后在promise函数中获取的值,在then中可以实现值的相应应用
Promise.all(arr).then(function(list){
    // 遍历查找
    list.forEach(item=>{
        console.log(item.width,item.src);
    })
})


// 将Promise对象数组中最先执行完成的内容通过后面then传入
/* Promise.race(arr).then(function(img){
    console.log(img);
}) */



2/* function loadImage(src){
    var p=new Promise(function(resolve,reject){
        var img=new Image();
        // resolve 是表示正确完成时执行的函数
        img.οnlοad=function(){
            // resolve(img);就是回调函数
            // 将数据传入给then的第一个函数
            resolve(img);
        }
        // reject 是表示正确完成时执行的函数
        img.οnerrοr=function(){
            reject(src);
        }
        // 赋值路径地址
        img.src=src;
    });
    return p;
}

// 生成器函数
function* fn(){
    // 每一次等待加载完成后,在加载下一个
    yield loadImage("./img/3-.jpg").then(function(img){
        console.log(img.src,img.width);
    })
    yield loadImage("./img/4-.jpg").then(function(img){
        console.log(img.src,img.width);
    })
    yield loadImage("./img/5-.jpg").then(function(img){
        console.log(img.src,img.width);
    })
    yield loadImage("./img/6-.jpg").then(function(img){
        console.log(img.src,img.width);
    })
}
// 循环按照顺序完成
for(var value of fn()){

} */

function loadImage(src){
    return new Promise(function(resolve,reject){
        var img=new Image();
        img.onload=function(){
            resolve(img);
        }
        img.onerror=function(){
            reject(src+"这个地址错误");
        }
        img.src=src;
    })
}
function* fn(){
    for(var i=3;i<80;i++){
        yield loadImage(`./img/${i}-.jpg`);
    }
}
var s=fn();
// value就是Promise对象
// 将断点的值返回给value变量 
var value=s.next().value;
fns();

function fns(){
    value.then(function(img){
        console.log(img);
        // value值不断的进行替换
        value=s.next().value;
        // 当前value有值时就继续执行
        if(value) fns();
    })
}


3function loadImage(src){
    var p=new Promise(function(resolve,reject){
        var img=new Image();
        // resolve 是表示正确完成时执行的函数
        img.onload=function(){
            // resolve(img);就是回调函数
            // 将数据传入给then的第一个函数
            resolve(img);
        }
        // reject 是表示正确完成时执行的函数
        img.onerror=function(){
            reject(src);
        }
        // 赋值路径地址
        img.src=src;
    });
    return p;
}

// async 异步
// await 等待的意思,一步步的往下加载
/* async function fn(){
    await loadImage("./img/3-.jpg").then(function(img){
        console.log(img.src,img.width);
    });
    await loadImage("./img/4-.jpg").then(function(img){
        console.log(img.src,img.width);
    });
    await loadImage("./img/5-.jpg").then(function(img){
        console.log(img.src,img.width);
    });
    await loadImage("./img/6-.jpg").then(function(img){
        console.log(img.src,img.width);
    });
}
fn(); */

async function fn(){
    var arr=[];
    for(var i=3;i<80;i++){
        await loadImage("./img/"+i+"-.jpg").then(function(img){
            arr.push(img);
        })
    }
    arr.forEach(item=>{
        console.log(item.src,item.width);
    });
    // 将Promis对象返回出去
    // return arr;
}
fn();

// fn执行时返回一个Promis对象
/* var p=fn();
// 这里相当于就是执行了resolve的内容
p.then(function(list){
    console.log(list);
}); */

// fn这个函数使用async,表示这个函数是一个异步函数
// 这个函数中就可以使用await,awiat作用就是让异步变为同步等待,异步变成了阻塞式等待
// 当异步全部完成时,再继续向后运行
// 加载一个完成后,循环一个
// async函数中的await后面只能跟的是Promise对象
// async函数执行后返回的是一个Promis对象
var p=new Promise(function(resolve,reject){
    var i=3;
    if(i<2){
        resolve(i);
    }else{
        reject(i);
    }
});
p.then(function(i){
    console.log(i);
},function(i){
    console.log(i);
})
// 和下面写法一样
// p.then(function(i){
//     console.log(i);
// }).catch(function(i){
//     console.log(i);
// })


// Promise all();   处理多个异步按照顺序每个执行完成后返回
function loadImage(src){
    return new Priomse(function(resolve,reject){
        var img=new Image();
        img.onload=function(){
            resolve(img);
        }
        img.onerror=function(){
            reject(img);
        }
        img.src=src;
    });

    var arr=[];
    for(var i=3;i<80;i++){
        arr.push(loadImage("./img/"+i+"-.jpg"));
    }
    // 这个list参数arr这个Promise的对象数组中所有异步then中返回img按顺序组合成的数组
    // 将数组arr中的每个Promise对象异步完成后的then中的img按顺序加入到一个数组中,全部完成后返回这个数组
    Promise.all(arr).then(function(list){

    })
回调地狱
var num=3;
var list=[];
var img=new Image();
img.src="./img/"+num+"-.jpg";
img.onload=function(){
    list.push(img);
    num++;
    img=new Image();
    img.src="./img/"+num+"-.jpg";
    img.onload=function(){
        list.push(img);
        num++;
        img=new Image();
        img.src="./img/"+num+"-.jpg";
        img.onload=function(){
            list.push(img);
            num++;
            img=new Image();
            img.src="./img/"+num+"-.jpg";
            img.onload=function(){
                list.push(img);
                num++;
                img=new Image();
                img.src="./img/"+num+"-.jpg";
                img.onload=function(){
                    list.push(img);
                    num++;
                }
            }
        }
    }
}
Promise的作用是处理回调地狱
function loadImage(src){
    return new Promise(function(resolve,reject){
        var img=new Image();
        img.onload=function(){
            resolve(img);
        }
        img.onerror=function(){
            reject(src+"地址错误");
        }
        img.src=src;
    })
}

var arr=[];
var num=3;
loadImage("./img/"+num+"-.jpg").then(function(img){
    arr.push(img);
    num++;
    return loadImage("./img/"+num+"-.jpg");
}).then(function(img){
    arr.push(img);
    num++;
    return loadImage("./img/"+num+"-.jpg");
}).then(function(img){
    arr.push(img);
    num++;
    return loadImage("./img/"+num+"-.jpg");
}).then(function(img){
    arr.push(img);
    num++;
    return loadImage("./img/"+num+"-.jpg");
})


// Promise 创建执行Promise中的函数,执行resolve或者reject后挂起等待
// 等待当前任务列中的所有代码全部执行完成,然后在查找then中(catch中)的函数是否存在,如果存在,则调用
function loadImage(src){
    return new Promise(function(resolve,reject){
        // state===pending
        // 如果当前状态时pending状态,那么可以调用resolve或者reject
        // 如果不是,不能调用resolve和reject
        // 保证在整个Promise中,resolve或者reject调用的唯一性
        var i=3;
        if(i<5){
            resolve(i);//state===resolved
        }else{
            reject(i);//state===rejected
        }
    })
}
// 异步
console.log("aaa");
var s=loadImage("./img/3-.jpg").then(function(){
    console.log("bbb");
})
console.log("ccc");
console.log("ddd");
console.log(s);
ES7推出async、await
// async 函数执行后创建一个新的Promise对象返回出来
// 在async函数中return某个值就意味着执行resolve(值)
// async函数执行后实际就是返回一个Promise对象
// 与Promise的区别async函数执行后实际就是一个Promise对象
// 如果使用await,这个await必须需要配合async来使用

async function fn(){
    // await 必须是处理Promise对象的异步等待
    // await 完成我们的异步等待后再继续执行,这样等待叫做同步阻塞
    await Promise.resolve(10).then(function(num){
        console.log(num);
    })
    await Promise.resolve(10).then(function(num){
        console.log(num);
    })

    // await只能针对Promise起作用
    // 针对setTimeout不起作用
    await setTimeout(function(){
        console.log("aaa");
    },5000);
    await setTimeout(function(){
        console.log("bbb");
    })
    return 10;
}
var p=fn();
p.then(function(num){
    console.log(num);
})
红绿灯案例
css样式
div{
    width:50px;
    height: 50px;
    border: 1px solid #cccccc;
    background-color: #cccccc;
    border-radius: 50%;
    float: left;
    margin-left: 10px;
}
<div></div>
<div></div>
<div></div>

js
var divs=Array.from(document.querySelectorAll("div"));
var prev;
function setLight(light){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve(light);
        },30000);
    });
}

function changeLight(){
    setLight("red").then(function(light){
        setBackground(0,light);
        return setLight("yellow");
    }).then(function(light){
        setBackground(1,light);
        return setLight("green");
    }).then(function(light){
        setBackground(1,light);
        return setLight("light");
    })
}

function setBackground(num,light){
    if(prev){
        prev.style.backgroundColor="#cccccc";
    }
    prev=divs[num];
    prev.style.backgroundColor=light;
}

eventLoop

// 同步
// 同步所有代码是 任务流
// 由上至下一个任务接着一个任务执行
var x=3;
var y=4;
var z=x+y;
// 异步
// 微任务和宏任务两个
// 微任务 Promise async await
// 宏任务 setTimeout、setInterval

// 微任务遇到微任务,放在当前任务列的最低端
// 宏任务 遇到宏任务,放在下个新增任务列的最顶端
console.log("a");
setTimeout(function(){
    console.log("b");
},0);
console.log("c");
new Promise(function(resolve,reject){
    console.log("d");
    resolve();
}).then(function(){
    console.log("e");
})
// 打印顺序a、c、d、e、b
setTimeout(function(){
    console.log(1);
    new Promise(function(resolve,reject){
        resolve();
    }).then(function(){
        console.log(2);
    })
},0);
// 打印顺序1、2
setTimeout(function(){
    console.log(1);
},0);
setTimeout(function(){
    console.log(2);
},50);

new Promise(function(resolve,reject){
    resolve();
}).then(function(){
    console.log(3);
    setTimeout(function(){
        console.log(4);
    },0);
})
// 打印顺序3、1、4、2
setTimeout(function(){
    console.log(1);
    new Promise(function(resolve,reject){
        resolve();
    }).then(function(){
        console.log(2);
    })
},0);

Promise.resolve().then(function(){
    console.log(1);
    Promise.resolve().then(function(){
        console.log(2);
    })
    return Promise.resolve();
}).then(function(){
    console.log(3);
})
// 打印顺序1、2、3、1、2
Promise.resolve().then(function(){
    console.log(1);
    Promise.resolve().then(function(){
        console.log(2);
    });
    Promise.resolve().then(function(){
        console.log(3);
    });
});
Promise.resolve().then(function(){
    console.log(4);
});
async function fn(){
    console.log(1);
    await Promise.resolve().then(function(){
        console.log(2);
    })
    await Promise.resolve().then(function(){
        // return返回的是当前函数
        // 并没其它操作
        return 3;
    })
    await Promise.resolve().then(function(){
        console.log(4);
    })
}
fn().then(function(num){
    console.log(num);
})
// 打印顺序1、2、4、undefined
console.log(0);
setTimeout(console.log(1),0)
console.log(2);
// 打印顺序0/1/2
console.log("1");
new Promise(function(resolve,reject){
    console.log("2");
    resolve();
}).then(function(){
    console.log("3");
});

setTimeout(function(){
    console.log("4");
},0);

setTimeout(console.log("6"),1000);
console.log("5");
// 打印顺序1,2,6,5,3,4
console.log(1);
document.addEventListener("14",function(){
    console.log(14);
});
new Promise(function(resolve){
    resolve();
    console.log(2);
    setTimeout(function(){
        console.log(3);
    },0);
    Promise.resolve().then(function(){
        console.log(4);
        setTimeout(function(){
            console.log(5);
        },0);
        setTimeout(function(){
            (async function(){
                console.log(6);
                return function(){
                    console.log(7);
                };
            })().then(function(fn){
                console.log(8);
                fn();
            });
        },0);
    });
    new Promise(function(resolve){
        console.log(9);
        resolve();
    }).then(function(){
        new Promise(function(resolve,reject){
            console.log(10);
            reject();
        }).then(function(){
            setTimeout(function(){
                console.log(11);
            },0);
            console.log(12);
        }).catch(function(){
            console.log(13);
            var evt=new Event("14");
            document.dispatchEvent(evt);
        });
    });
});
setTimeout(function(){
    console.log(15);
    Promise.resolve().then(function(){
        console.log(16);
    });
},0);
// 打印顺序:1,2,9,4,10,13,14,3,15,16,5,6,8,7
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值