предисловие
Следующее, что нужно углубить, это цепной вызов then, который является самой запутанной частью реализации. Прежде чем читать, давайте углубимся в впечатление.
constructor -> fn --同步--> resolve(reject) -> then -> then 回调
constructor -> fn --异步--> then -> resolve(reject) -> then 回调
Будь то синхронный или асинхронный,then 回调函数
будет вresolve
После того, как он будет выполнен, он будет выполнен. Таким образом, можно понять, что только выполняяresolve
После этого сработаетthen 回调函数
исполнение.
Примечание. На этот раз я прочитал версию 3.0.0 then/promise, пожалуйста, отметьте исходный код.здесь.
интерпретировать
Давайте сначала посмотрим на пример кода:
var p1 = new Promise(function (resolve) {
setTimeout(function () {
resolve(1);
}, 1000);
})
p1.then(function (val) {
var p3 = new Promise(function (resolve) {
setTimeout(function () {
resolve(val + 1);
}, 1000);
});
return p3;
}).then(function (val) {
console.log(val);
});
Глядя на приведенный выше код, мы ясно видим, что были добавлены два новых экземпляра Promise, соответственно, с использованиемp1
а такжеp3
Выражать. Затем из предыдущей реализации метода then мы увидим, что он также возвращает экземпляр Promise, мы используемp2
Для представления экземпляра Promise, возвращаемого после выполнения функции then, для следующего различия.
this.then = function(onFulfilled, onRejected) {
return new Promise(function(resolve, reject) {
handle({ onFulfilled: onFulfilled, onRejected: onRejected, resolve: resolve, reject: reject })
})
}
Столкнувшись с приведенным выше кодом, давайте посмотрим, что представляют собой переменные:
- p1: самый внешний экземпляр Promise;
- p2: Экземпляр Promise, возвращенный p1, вызвавшим функцию then;
- p3: Экземпляр Promise, возвращенный функцией обратного вызова then для p1.
исполнительный лист
Рассмотрим порядок выполнения приведенного выше примера кода:
- Новый экземпляр Promise назначается p1, и выполняется функция fn;
- p1 вызывает свою функцию then, которая возвращает p2;
- p2 вызывает свою функцию then (которая фактически возвращает новый экземпляр Promise);
- Через одну секунду выполните функцию разрешения p1;
- Запускает функцию обратного вызова p1, после чего создается и возвращается p3;
- Еще через секунду p3 выполняет функцию разрешения;
- Запустите p2, затем функцию обратного вызова.
Сомнение: здесь p3 выполняет свою функцию разрешения, как он может вызвать функцию обратного вызова p2, не должен ли он запускать свою собственную функцию обратного вызова? ?
handle
Посмотрите на код из шага 5, вызовите функцию обратного вызова then для p1, а также вызовите функцию дескриптора в p1:
function handle(deferred) {
nextTick(function() {
var cb = state ? deferred.onFulfilled : deferred.onRejected
if (typeof cb !== 'function'){
(state ? deferred.resolve : deferred.reject)(value)
return
}
var ret
try {
ret = cb(value)
}
catch (e) {
deferred.reject(e)
return
}
deferred.resolve(ret)
})
}
будет выполняться первымonFulfilled
функция, то естьp1
Функция обратного вызова then, созданная в это времяp3
Возвращает назначение ret. Затем вызовите разрешение deferred, которое на самом деле вызываетp2
решить, будетp3
Передать в качестве параметра.
resolve
Отложенные вызовы разрешаются, и сначала удаляется код, который не будет выполняться:
function resolve(newValue) {
if (delegating)
return
resolve_(newValue)
}
function resolve_(newValue) {
if (state !== null)
return
try {
if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.')
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
var then = newValue.then
if (typeof then === 'function') {
delegating = true
then.call(newValue, resolve_, reject_)
return
}
}
} catch (e) { reject_(e) }
}
потому что новое значениеp3
, посчитав, что это объект с then, будет вызвана его функция then, котораяp2
разрешение_ какp3
Затем передается функция обратного вызова.
еслиp3
Когда разрешение выполнено, будет выполнена его функция обратного вызова, т.е.p2
разрешение_. еслиp2
При выполнении resolve_ будет выполнена его собственная функция обратного вызова.
Здесь вы можете думать о коде так: все переменные в resolve_p2
Переменные:
then.call(newValue, function resolve_ (newValue) {
// 更新状态
state = true
// 记住 resolve 的参数
value = newValue
finale()
}, reject_);
а такжеp2
Функция обратного вызова then — это связанная функция обратного вызова then в примере кода. Таким образом, реализован цепной вызов then.
Сказав кучу слов выше, это может быть немного сложно понять.Давайте сделаем снимок, чтобы понять это.
delegating
Коротко о переменныхdelegating
,потому чтоp2
Разрешение_ может быть вызвано вызовом разрешения или вызовомp3
затем обратный вызов для запуска. когда прошлоp3
тогда обратный вызов для запуска, когдаdelegating
будет установлено значение true, в этот момент он будет отключенp2
Случай, вызванный вызовом разрешения.
function resolve(newValue) {
if (delegating)
return
resolve_(newValue)
}
nextTick
Зная порядок всего тогдашнего цепного звонка, давайте взглянем на него в последний раз.nextTick
. В моем понимании использованиеnextTick
Причина в том, что функция обратного вызова then не будет выполняться до тех пор, пока не будет выполнен весь код then.
В противном случае следующий код,p1
Функция обратного вызова выполняется первой, а затем выполняется вторая функция, что нарушает концепцию, согласно которой Promise — это очередь микрозадач в ES6.
var p1 = new Promise(function (resolve) {
resolve(1);
})
p1.then(function (val) {
var p3 = new Promise(function (resolve) {
resolve(val + 1);
});
return p3;
}).then(function (val) {
console.log(val);
});
Суммировать
Цепной вызов промиса then заключается в простом использовании нового экземпляра промиса в качестве моста.Когда промис, возвращенный в предыдущей функции обратного вызова then, разрешается, он запускает мост для выполнения своего обратного вызова then.
Если это немного сложно понять, не волнуйтесь, прочитайте статью несколько раз, чтобы понять это.