promise使用及解析及事件循环

10 篇文章 0 订阅
3 篇文章 0 订阅

同步for循环执行和promise

for(let a = 0;a<1000;a++){
	new Promise((resolve,reject)=>{
		resolve("123")
	}).then(res=>{
		console.log("异步任务",res)
	})
	console.log("同步",a)
	
}

执行结果:
在这里插入图片描述

事件循环:当我们的代码从上到下同步执行时,遇到setTimeout就记时,当时间到时就把此事件放到事件队列中,遇到微任务就把微任务放到微任务空间,代码会继续向下执行,直到同步代码执行完毕。
完毕后,会看看微任务空间中有没有微任务,有就把微任务空间中的微任务全部执行,然后去队列中取我们的事件执行,执行时若有微任务继续放到微任务空间,当此事件执行完毕,还会把微任务空间中的微任务全部执行完毕,然后再去取队列中的异步任务。。。。反复循环

如果希望得到一个 Promise 对象,比较方便的方法就是直接调用Promise.resolve()方法。

const p = Promise.resolve('Hello');

p.then(function (s) {
  console.log(s)
});

setTimeout(function () {
  console.log('three');
}, 0);

Promise.resolve().then(function () {
  console.log('two');
});

console.log('one');
//one
//two
//three

上面代码中,setTimeout(fn, 0)在下一轮“事件循环”开始时执行,Promise.resolve()在本轮“事件循环”结束时执行,console.log(‘one’)则是立即执行,因此最先输出。

setTimeout为什么会在Promise之后执行?
查看(宏任务、微任务 event loop)阮一峰版本
知乎的版本
思否的版本

首先输出的是Promise。然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出。

function timeout(ms){
				
	return new Promise((resolve,reject)=>{
		setTimeout(resolve,ms,'done')
		console.log("1")
	})
};
timeout(0).then((value)=>{
	console.log(value)
});
function test(name){
	console.log(name);
}
test('2')
//1
//2
//done

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。

let promise = new Promise((resolve,reject)=>{
	return resolve("123")
})
promise.then(res=>{
	console.log(res)
	return res
}).then(value=>{
	console.log('value:',value)
	return value;
}).then(next=>{
	console.log('next:',next)
})
//123
//value: 123
//next: 123

p1是一个 Promise,3 秒之后变为rejected。p2的状态在 1 秒之后改变,resolve方法返回的是p1。由于p2返回的是另一个 Promise,导致p2自己的状态无效了,由p1的状态决定p2的状态。所以,后面的then语句都变成针对后者(p1)。又过了 2 秒,p1变为rejected,导致触发catch方法指定的回调函数

let p1 = new Promise(function(resolve,reject){
	console.log(1)
	setTimeout(()=> reject(new Error('fail')),3000);
	console.log(3)
})
let p2 = new Promise((resolve,reject)=>{
	console.log(2)
	setTimeout(()=>resolve(p1),1000)
})
p2.then(res=>{
	console.log(res)
}).catch(err=>{
	console.error(err)
})
setTimeout(()=>{
	console.log(4)
},2999)

setTimeout(()=>{
	console.log(5)
},3001)
//1
//3
//2
//4
//fail
//5

多个异步调用

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function (comments) {
  console.log("resolved: ", comments);
}, function (err){
  console.log("rejected: ", err);
});

等同于

getJSON("/post/1.json").then(
  post => getJSON(post.commentURL)
).then(
  comments => console.log("resolved: ", comments),
  err => console.log("rejected: ", err)
);

Promise.all()

javascriptconst p = Promise.all([p1, p2, p3]);

p的状态由p1、p2、p3决定,分成两种情况。

(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

let p1 = new Promise((resolve,reject)=>{
	return resolve(1)
});
let p2 = new Promise((resolve,reject)=>{
	return reject(2)
})
let p = Promise.all([p1,p2]);
p.then(([r1,r2])=>{
	console.log(r1,r2)
}).catch(err=>{
	console.log(err)
})
//2

let p1 = new Promise((resolve,reject)=>{
	return resolve(1)
});
let p2 = new Promise((resolve,reject)=>{
	return resolve(2)
})
let p = Promise.all([p1,p2]);
p.then(([r1,r2])=>{
	console.log(r1,r2)
}).catch(err=>{
	console.log(err)
})
//1 2

Promise.race()
哪个先执行,返回哪个结果

let p1 = new Promise((resolve,reject)=>{
		return resolve(1)
	});
	let p2 = new Promise((resolve,reject)=>{
		return reject(2)
	})
	
	//Promise.race();
	const p = Promise.race([p1,p2,
		new Promise(function(resolve,reject){
			setTimeout(()=>{
				reject('time out')
			},2000)
		})
	])
	p.then(res=>{
		console.log('resolve',res)
	}).catch(err=>{
		console.log('reject',err)
	})
	// resolve 1

当遇到一个未知函数时,即不知道是同步函数还是异步函数,但想通过promise的then/catch执行后续操作

const f = () => console.log('now');
Promise.resolve().then(f);
console.log('next');
// next
// now

上面写法的缺点:如果f是同步函数,那么它会在本轮事件循环的末尾执行。
解决以上问题
方法一:

(async () => f())()
.then(...)
.catch(...)

方法二:

const f = () => console.log('now');
(
  () => new Promise(
    resolve => resolve(f())
  )
)();
console.log('next');
// now
// next

//等同于

const f = () => console.log('now');
Promise.try(f);
console.log('next');
// now
// next

源码解析:

function Promise (executor) {
    var self = this;
    self.status = 'pending';
    self.value;
    self.reason;
    self.onResolvedCallbacks = []; // 存放所有成功的回调。
    self.onRejectedCallbacks = []; // 存放所有失败的回调。
    function resolve(value) {
        if (self.status === 'pending') {
            self.status = 'resolved';
            self.value = value;
            self.onResolvedCallbacks.forEach(function (fn) {
                fn();
            })
        }
    }

    function reject(reason) {
        if (self.status === 'pending') {
            self.status = 'rejected';
            self.reason = reason;
            self.onRejectedCallbacks.forEach(function (fn) {
                fn();
            })
        }
    }
    try {
        executor(resove, reject);
    } catch (e) {
        reject(e);
    }
}

function resolvePromise (promise2, x, resolve, reject) {
    if (promise2 === x) { // 防止自己等待自己
        return reject(new TypeError('循环引用了'));
    }
    let called; // 表示Promise有没有被调用过
    // x是object或者是个function
    if ((x !== null && typeof x === 'object') || typeof x === 'function') {
        try {
            let then = x.then;
            if (typeof then === 'function') {
                then.call(x, function (y) {
                    if (called) { // 是否调用过
                        return;
                    }
                    called = true;
                    resolvePromise (promise2, y, resolve, reject)
                }, function (r) {
                    if (called) { // 是否调用过
                        return;
                    }
                    called = true;
                    reject(r);
                });
            } else { // 当前then是一个普通对象。
                resolve(x)
            }
        } catch (e) {
            if (called) { // 是否调用过
                return;
            }
            called = true;
            reject(e);
        }
    } else {
        if (called) { // 是否调用过
            return;
        }
        called = true;
        resolve(x);
    }
}

Primsie.prototype.then = function(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (data) { return data;};
    onRejected = typeof onRejected === 'function' ? onRejected : function (err) { throw err;};
    var self = this;
    const promise2 = new Promise(function (resolve, reject) {
        if (self.status === 'resolved') {
            setTimeout(function() {
                try {
                    const x = onFulfilled(self.value);
                    resolvePromise(promise2, x, resolve, reject);
                } catch(e) {
                    reject(e);
                } 
            }, 0)
        }

        if (self.status === 'rejected') {
            setTimeout(function() {
                try {
                    const x = onRejected(self.reason);
                    resolvePromise(promise2, x, resolve, reject);
                } catch(e) {
                    reject(e);
                }
            }, 0)
        }
        if (self.status === 'pending') {
            self.onResolvedCallbacks.push(function () {
                setTimeout(function() {
                    try {
                        const x = onFulfilled(self.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch(e) {
                        reject(e);
                    }
                }, 0)
            });
            self.onRejectedCallbacks.push(function() {
                setTimeout(function() {
                    try {
                        const x = onRejected(self.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch(e) {
                        reject(e);
                    }
                }, 0)
            });
        }
    })
    return promise2;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值