代码执行顺序
const first = () =>
new Promise((resolve, reject) => {
resolve(2);
console.log(3);
let p = new Promise((resolve, reject) => {
console.log(7);
resolve(1);
})
p.then(arg => {
console.log(arg);
})
})
first().then(arg => {
console.log(arg);
})
console.log(4);
复制代码
Promise构造函数
function Promise(resolver) {
if (typeof resolver !== 'function') {
throw new TypeError('resolver must be a function');
}
this.state = PENDING;
this.queue = [];
this.outcome = void 0;
if (resolver !== INTERNAL) {
safelyResolveThenable(this, resolver);
}
}
复制代码
- 执行first()
- new Promise进入构造函数
- 执行safelyResolveThenable
function safelyResolveThenable(self, thenable) {
var called = false;
function onError(value) {
if (called) {
return;
}
called = true;
handlers.reject(self, value);
}
function onSuccess(value) {
if (called) {
return;
}
called = true;
handlers.resolve(self, value);
}
function tryToUnwrap() {
thenable(onSuccess, onError);
}
var result = tryCatch(tryToUnwrap);
if (result.status === 'error') {
onError(result.value);
}
}
复制代码
- 实际执行
tryToUnwrap
的thenable(onSuccess, onError);
thenable
= 当初Promise传入的如下代码
(resolve, reject) => {
resolve(2);
console.log(3);
let p = new Promise((resolve, reject) => {
console.log(7);
resolve(1);
})
p.then(arg => {
console.log(arg);
})
}
复制代码
- 执行
resolve(2)
- 即执行
function onSuccess(value) {
if (called) {
return;
}
called = true;
// value = 2
handlers.resolve(self, value);
}
复制代码
- handlers.resolve
handlers.resolve = function (self, value) {
// 每次执行都过tryCatch,这也是为何能最后Catch到的缘由
var result = tryCatch(getThen, value);
if (result.status === 'error') {
return handlers.reject(self, result.value);
}
var thenable = result.value;
// thenable = undefined
if (thenable) {
safelyResolveThenable(self, thenable);
} else {
// 进入这里
self.state = FULFILLED;
// outcome记录2
self.outcome = value;
var i = -1;
// self.queue = []
var len = self.queue.length;
// 没有执行的
while (++i < len) {
self.queue[i].callFulfilled(value);
}
}
return self;
};
复制代码
- 同样的执行顺序
- 打印7,执行resolve(1);
- getThen(这步返回undefined),与本题无关
function getThen(obj) {
// Make sure we only access the accessor once as required by the spec
var then = obj && obj.then;
// 判断传入参数是否是Promise
if (obj && (typeof obj === 'object' || typeof obj === 'function') && typeof then === 'function') {
return function appyThen() {
then.apply(obj, arguments);
};
}
}
复制代码
- then
Promise.prototype.then = function (onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function' && this.state === FULFILLED ||
typeof onRejected !== 'function' && this.state === REJECTED) {
return this;
}
// 新生成Promise
var promise = new this.constructor(INTERNAL);
// this.state = "FULFILLED"
if (this.state !== PENDING) {
// 进入这里resolver = onFulfilled
var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
// this.outcome = 1, promise = 新构造的
unwrap(promise, resolver, this.outcome);
} else {
this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
}
return promise;
};
复制代码
- unwrap
function unwrap(promise, func, value) {
// task = immediate里面的funciton
immediate(function () {
var returnValue;
try {
returnValue = func(value);
} catch (e) {
return handlers.reject(promise, e);
}
if (returnValue === promise) {
handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));
} else {
handlers.resolve(promise, returnValue);
}
});
}
复制代码
immediate.js
var Mutation = global.MutationObserver || global.WebKitMutationObserver;
var called = 0;
var observer = new Mutation(nextTick);
var element = global.document.createTextNode('');
observer.observe(element, {
characterData: true
});
scheduleDrain = function () {
element.data = (called = ++called % 2);
};
function immediate(task) {
if (queue.push(task) === 1 && !draining) {
scheduleDrain();
}
}
var draining;
var queue = [];
function nextTick() {
draining = true;
var i, oldQueue;
var len = queue.length;
while (len) {
oldQueue = queue;
queue = [];
i = -1;
while (++i < len) {
oldQueue[i]();
}
len = queue.length;
}
draining = false;
}
复制代码
- immediate
// 当queue = [], draining = undefined
function immediate(task) {
if (queue.push(task) === 1 && !draining) {
scheduleDrain(); // 执行scheduleDrain
}
}
复制代码
- scheduleDrain执行
- 执行first().then
- 再次执行14步骤,可是只push,不执行里面的scheduleDrain
- 而后打印console.log(4);
- 如今执行nextTick回调
- 按照先进先出,打印1,2