Promise 解决阻塞式同步,将异步变为同步

Posted 勇敢*牛牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Promise 解决阻塞式同步,将异步变为同步相关的知识,希望对你有一定的参考价值。

Promise 解决阻塞式同步,将异步变为同步

一、样式

 var p = new Promise(function(reslove,reject)
     reslove()//在构造的时候就执行这个函数了
 );
 p.then(function()

 ).catch(function()
     
 )
————————————————————————————————————————————————————————————————————————————————————
new Promise(function(resolve,reject)
    resolve();
).then(function()
    // resolve时执行
,function()
    // reject时执行
)
  • Promise需要实例化完成创建一个Promise对象
  • Promise实例化的构造函数中传入一个回调函数
  • 回调函数中有两个参数,一个是resolve,一个是reject
  • 当成功后调用resolve函数,失败后调用reject函数
  • 并且可以通过resolve或者reject函数传递一个参数
  • Promise实例化的对象执行两个方法一个是then,一个 是catch
  • 这两个方法中有两个回调函数,当执行resolve 时,调用then中回调函数,当执行reject时调用catch 中的回调函数
  • 在Promise实例化的构造中只能调用一次resolve或者一次 reject,调用一次后,再次调用任何一个resolve或者reject都是无效的

顺序输出异步abc

new Promise(function(resolve,reject)
    setTimeout(function()
        resolve()
    ,1000)
).then(function()
    console.log('a');
    return new Promise(function(resolve,reject)
        setTimeout(function()
        resolve()
        ,500)
    )
).then(function()
    console.log('b');
    return new Promise(function(resolve,reject)
        setTimeout(function()
            resolve()
        ,1000)
    )
).then(function()
    console.log('c');
)
输出:
a
b
c

顺序输出异步红绿灯

function setTime(time)
    return new Promise(function(resolve,reject)
        setTimeout(function()
            resolve()
        ,time)
    )

setTime(100).then(function()
    console.log('黄灯');
    return setTime(1000)
).then(function()
    console.log('绿灯');
    return setTime(500)
).then(function()
    console.log('红灯');

)

封装返回一个Promise对象

//次函数返回一个Promise对象
function setTime(time)
    return new Promise(function(resolve,reject)
        setTimeout(function()
            resolve();
        ,time);
    )

Promise对象执行方法then
setTime().then(function()
    console.log('aaa');
)
//aaa

连缀使用Promise

function setTime(time)
    return new Promise(function(resolve,reject)
        setTimeout(function()
            resolve();
        ,time);
    )

setTime(500).then(function()
    console.log('aaa');
    return setTime(1000);
).then(function()
    console.log('bbb');
    return setTime(100);
).then(function()
    console.log('ccc');
)

aaa
bbb
ccc

预加载图片

让异步变成一个阻塞式同步

function loadImage(src)
    return new Promise(function(resolve,reject)
        var img = new Image();
        img.src = src;
        /* 加载完成时执行一下代码 */
        img.onload = function()
            /* 执行resolve回调函数,传入参数img对象 */
            resolve(img)
        
    )

var arr = [];
/* Promise对象构造的时候执行了回调函数resolve,而执行resolve会调用方法then中的回调函数 */
loadImage("./img/img_15.JPG").then(img =>
    arr.push(img)
    return loadImage("./img/img_16.JPG")
).then(img =>
    arr.push(img)
    return loadImage("./img/img_17.JPG")
).then(img =>
    arr.push(img)
    console.log(arr);
)

function loadImage(src)
    return new Promise(function(resolve,reject)
        var img = new Image();
        img.src = src;      
        img.onload = function()
            resolve(img)
        
        img.onerror = function()
            reject(src)
        
    )

//错误时执行代码
var arr = [];
loadImage("./img/img_11.JPG").then(img =>
    arr.push(img)
).catch(function(src)
    console.error("error:"+src);
)

连续then时,相当于自动创建一个return promise并且执行resolve

new Promise(function(resolve,reject)
   setTimeout(function()
    resolve();
   ,500);
).then(function()
    console.log("aa");
    // 连续then,并没有return新的Promise时,相当于自动return Promise执行了resolve
    // return new Promise(function(resolve,reject)
    //     resolve();
    // )
).then(function()
    console.log("bb");
)
两种快捷写法
Promise.resolve().then(function()

)
Promise.reject().catch(function()

)      

图片整体预加载

  • 先把所有异步使用Promise封装后放在一个数组中
  • 然后通过Promise.all传入这个数组,这时候
  • 所有异步执行resolve传入的参数就会被按照
  • 顺序放在一个数组中,并且通过then中参数返回
function loadImage(src)
    return new Promise(function(resolve,reject)
        var img = new Image();
        img.src = src;
        img.onload = function()
            resolve(img)
        
        img.onerror = function()
            reject(src)
        
    )

arr = [];
for(var i=15;i<19;i++)
    var p = loadImage(`./img/img_$i.JPG`);
    arr.push(p);

console.log(arr);
Promise.all(arr).then(function(list)
    list.forEach(item=>console.log(item));
)

谁先加载完就显示谁

Promise.race(arr).then(function(img)
	console.log(img);
)

最简点的异步加载async,awiat

function loadImage(src)
    return new Promise(function(resolve,reject)
        var img = new Image();
        img.src = src;
        img.onload = function()
            resolve(img)
        
        img.onerror = function()
            reject(src)
        
    )

init();
async function init()
    arr = [];
    for(var i=15;i<19;i++)
    	/*自动等待将loadImage函数执行的resolve函数的结果值返回给p*/
        var p = await loadImage(`./img/img_$i.JPG`);
        arr.push(p);
    
    console.log(arr);

  • 异步可以包装成一个promise函数
  • await 只能等待Promise,其他的异步都不能等待
  • 要使用await ,就需要在await所属的函数外使用async
  • 没有async不能单独使用await
  • async函数执行后将会返回一个promise对象
  • async函数中return 结果就相当于promise执行了resolve(return的结果)

当使用try catch拦截promise中reject时,必须放在async await函数中
因为这个是异步等待后才报错的

async function init()
     try
       await loadImage("./img/img_14.JPG").then(function(img)
             console.log(img);
         )
     catch(e)
         console.log(e)
     
   

宏任务和微任务

执行顺序

同步-->微任务-->微任务中的微任务-->宏任务-->宏任务中的微任务-->微任务中的宏任务-->微任务中的宏任务中的微任务-->宏任务中宏任务
new Promise(function (res, rej) 
        // console.log(2);
    )
    .then(function () 
        // console.log(3);
        Promise.resolve().then(function () 
            // console.log(5);
            setTimeout(function () 
                console.log(6);
                Promise.resolve().then(function () 
                    console.log(7);
                );
                setTimeout(function () 
                    console.log(8);
                , 0);
            , 0);
        );
    )
    .then(function () 
        // console.log(4);
    );

setTimeout(function () 
    // console.log(9);
    new Promise(function (res) 
        res();
        // console.log(10);
    ).then(function () 
        // console.log(11);
    );
);

Promise.resolve().then(function () 
    setTimeout(function () 
        Promise.resolve().then(function () 
            // console.log(12);
        );
        // console.log(13);
    , 0);
);


setTimeout(function () 
    setTimeout(function () 
        setTimeout(function () 
            Promise.resolve().then(function () 
                console.log(14);
            );
            console.log(15);
        , 0);
        console.log(16);
    , 0);
    // console.log(17);
, 0);


// console.log(18);


new Promise(function (res) 
    // console.log(19);
    setTimeout(function () 
        // console.log(20);
    , 0);
);

以后看…………………………

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);
                ;
            )()以上是关于Promise 解决阻塞式同步,将异步变为同步的主要内容,如果未能解决你的问题,请参考以下文章

阻塞式/非阻塞式与同步/异步的区别

将已经存在的异步请求callback转换为同步promise

promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解

阻塞式I/0 和 非阻塞式I/O 同步异步详细介绍

深入理解“同步-异步-阻塞-非阻塞”

实现Promise