дляPromise
, я считаю, что большинство людей уже поняли и могут умело использовать его различные методы, но может быть неясно исследовать его основные принципы.Эта статья была написана после периода изучения.Она содержит собственное правоPromise
понять и следовать пошаговому почеркуPromise
так же какthen
Метод, я надеюсь, что эта статья может помочь вам.
Узнать обещания
Значение обещаний
Promise
Это решение для асинхронного программирования, ES6 вписал его в стандарт языка. так называемыйPromise
Это контейнер, в котором хранятся события (обычно асинхронные операции), которые завершатся в будущем.результат.
Promise
Объекты имеют следующие две характеристики:
- На состояние объекта не влияет внешний мир.
Promise
Объект представляет собой асинхронную операцию и имеет три состояния:pending
(в ходе выполнения),fulfilled/resolved
(удалось),rejected
(не удалось). Только результат асинхронной операции может определить текущее состояние, и никакая другая операция не может изменить это состояние. - Как только состояние изменилось, оно больше никогда не изменится, и этот результат можно получить в любое время.
Promise
Есть только две возможности для изменения состояния объекта: отpending
сталиfulfilled
и изpending
сталиrejected
. Пока эти две ситуации имеют место, состояние будет затвердевшим и не изменится, и всегда будет поддерживать этот результат, который называетсяresolved
(уже доработано). Если изменение уже произошло, выPromise
Добавьте к объекту функцию обратного вызова, и вы сразу же получите этот результат.
Promise
Преимущества:
Асинхронные операции можно выразить в потоке синхронных операций, избегая уровней вложенных функций обратного вызова.
Основное использование
ES6 заявляет,Promise
Объект — это конструктор, используемый для генерацииPromise
пример.
const promise = new Promise((resolve,reject)=>{
//此处执行一些异步操作(调用后台API,定时器等)
if(/*异步操作成功*/){
resolve(value);
}else{
reject(error)
}
})
//其中两个函数的参数值分别为成功和失败后想要传递的结果
Promise
Конструктор принимает функцию в качестве параметра, два параметра функцииresolve
а такжеreject
. Это две функции, заданныеJavaScript
Двигатель предоставляется, не нужно разворачивать его самостоятельно.
resolve
Функция функции состоит в том, чтобыPromise
Состояние объекта меняется с «Не завершено» на «Успешно» (т.е. сpending
сталиresolved
), вызывается при успешном выполнении асинхронной операции, и результат асинхронной операции передается в качестве параметра;reject
Функция функции состоит в том, чтобыPromise
Состояние объекта меняется с «Незавершенный» на «Неудачный» (т.е. сpending
сталиrejected
), вызываемый при сбое асинхронной операции, и передает сообщение об ошибке асинхронной операции в качестве параметра.
then
Метод может принимать две функции обратного вызова в качестве параметров. Первая функция обратного вызоваPromise
Состояние объекта становитсяresolved
При вызове вторая функция обратного вызоваPromise
Состояние объекта становитсяrejected
когда звонили. Среди них вторая функция не является обязательной и не обязательно. Обе функции принимаютPromise
Значение, переданное из объекта в качестве параметра.
promise.then(res=>{
//对于成功回调接受的数据做处理
},err=>{
//对于失败的回调数据做处理
})
Примечание:Promise
Он будет выполнен, как только будет создан.
Promise.prototype.then()
Promise
экземпляр имеетthen
метод, то естьthen
Метод определен на объекте-прототипеPromise.prototype
выше, его функция состоит в том, чтобыPromise
Функция обратного вызова, когда экземпляр добавляет изменения состояния. Я сказал раньше,then
Первый параметр методаresolved
Функция обратного вызова состояния, второй параметр (необязательный)是rejected
Функция обратного вызова статуса.
then
метод возвращает новыйPromise
Пример (заметьте, не оригинальныйPromise
пример). Поэтому можно использовать метод цепной записи, т.then
После вызова метода другогоthen
метод. После завершения первой функции обратного вызова возвращаемый результат будет использоваться в качестве параметра, как и вторая функция обратного вызова.
прикованныйthen
, вы можете указать набор функций обратного вызова, которые будут вызываться по порядку. (в ES7async/await
) Также могут быть достигнуты цепные вызовы, кроме того,Promise
изall
Методы могут выполняться параллельно.
понимать основыPromise
а такжеthen
После этого мы можем создать свой собственныйPromise
.
Рукописное обещание
напиши первымPromise
конструктор, из вышеперечисленногоPromise
Из использования видно, что его параметр является функцией, также известной как функция-исполнитель (executor), и функция-исполнитель будет вызвана сразу, и функция-исполнитель также получит два параметра, оба из которых являются функциями .
function Promise(executor) {
executor(resolve, reject);
}
Promise
Самый главный способ этоthen
метод, поэтому для того, чтобы экземпляр вызывал этот метод, мы должны написать этот метод в его цепочке прототипов, и он принимает два параметра: обратный вызов в случае успеха и обратный вызов в случае неудачи.
Promise.prototype.then=function(onResolved,onRejected){
}
продолжать писатьPromise
функцию, потому чтоnew
Исходящий экземпляр имеет состояние по умолчаниюpending
, то через исполнителяexecutor
воплощать в жизньresolve
а такжеreject
Две функции для изменения состояния.
function Promise(executor) {
let self=this; //保留this。防止后面方法出现this只想不明的问题
self.status='pending'; //promise的默认状态是pending
function resolve(){
self.status='resolved'; //成功函数将其状态修改为resolved
}
function reject(){
self.status='rejected'; //失败函数将其函数修改为rejected
}
executor(resolve, reject);
}
чтобы убедиться, чтоPromise
После изменения состояния экземпляра его нельзя изменить снова, и его необходимо оценить.
function Promise(executor) {
let self = this; //保留this。防止后面方法出现this只想不明的问题
self.status = 'pending'; //promise的默认状态是pending
self.success = undefined; //保存成功回调传递的值
self.error = undefined; //保存失败回调传递的值
function resolve() {
if (self.status === 'pending') {
self.status = 'resolved'; //成功函数将其状态修改为resolved
}
}
function reject() {
if (self.status === 'pending') {
self.status = 'rejected'; //失败函数将其函数修改为rejected
}
}
executor(resolve, reject);
}
После этого вам нужно сохранить результаты успеха или неудачи после вызова
function Promise(executor) {
let self = this; //保留this。防止后面方法出现this只想不明的问题
self.status = 'pending'; //promise的默认状态是pending
self.success = undefined; //保存成功回调传递的值
self.error = undefined; //保存失败回调传递的值
function resolve(success) {
if (self.status === 'pending') {
self.status = 'resolved'; //成功函数将其状态修改为resolved
self.success=success; //将成功的值保存起来
}
}
function reject(error) {
if (self.status === 'pending') {
self.status = 'rejected'; //失败函数将其函数修改为rejected
self.error=error; //将失败的值保存起来
}
}
executor(resolve, reject);
}
Вот практический пример (Express использует Promise для сохранения возвращаемого значения)
Примечание. В этом примере используется асинхронная обработка функций, связанные вызовы, и он помещен здесь только для иллюстрации приведенных выше понятий.
когда исполнитель звонитresolve
После функции,then
Выполняется первый параметр в функции (успешный обратный вызов), и сохраненное значение передается вthen
Первая функция в качестве аргумента и при вызове исполнителяreject
После функции,then
Второй параметр в функции (обратный вызов сбоя) выполняется, и сохраненное значение передается вthen
Вторая функция в качестве аргумента.
Promise.prototype.then = function (onResolved, onRejected) {
let self = this;
if (self.status === 'resolved'); {
onResolved(self.success); //将resolve函数保留的成功值传递作为参数
}
if (self.status === 'rejected') {
onRejected(self.error); //将reject函数保留的失败值传递作为参数
}
}
В соответствии с приведенным выше примером, приведите егоthen
использование
слишком далекоPromise
Простая структура была в основном завершена, простой тест
let promise = new Promise((resolve, reject) => {
console.log('start');
resolve('success data');
})
promise.then(res => {
console.log("res", res);
}, err => {
console.log("err", err);
})
Результаты теста
start
res success data
Вышеуказанные шаги просто реализуют синхронную обработку, а затем реализуют асинхронную обработку и реализуют несколько вызовов экземпляра.then
метод (не связанный)
потому чтоjs
Он однопоточный.Простое понимание цикла событий на стороне браузера заключается в том, чтобы сначала выполнять синхронные задачи, а затем выполнять асинхронные задачи. Задачи синхронизации хранятся в стеке вызовов.Главный поток будет выполнять задачи синхронизации в первую очередь.Когда все задачи синхронизации в стеке вызовов выполнены и основной поток пуст, основной поток перейдет в очередь задач, чтобы проверить, есть ли прописаны асинхронные задачи, callback-функция, если есть, будет выполняться, если нет, то будет ждать. Асинхронные задачи в очереди задач далее делятся на микрозадачи и макрозадачи, обе из которых также имеют соответствующие последовательности выполнения. Подробности могут подождать в следующей статье
Ближе к дому, реализуйте асинхронную обработку и множественные вызовы
еслиPromise
Обработка является асинхронной функцией, тогда, когдаthen
В это время параметры в функции привода будут помещены в очередь асинхронных задач, то есть в это времяPromise
Экземпляры по-прежнему находятся в состоянии по умолчаниюpending
, нет изменений, то мы не знаем, что делать в это времяthen
Если вы не знаете, какая функция обратного вызова будет выполнена, вам нужно сохранить эти две функции обратного вызова, дождаться подходящего времени, чтобы определить, какую функцию вызывать.
function Promise(executor) {
let self = this; //保留this。防止后面方法出现this只想不明的问题
self.status = 'pending'; //promise的默认状态是pending
self.success = undefined; //保存成功回调传递的值
self.error = undefined; //保存失败回调传递的值
self.onSuccessCallbacks = []; //存放成功的回调
self.onErrorCallbacks = []; //存放失败的回调
function resolve(success) {
if (self.status === 'pending') {
self.status = 'resolved'; //成功函数将其状态修改为resolved
self.success = success; //将成功的值保存起来
self.onSuccessCallbacks.forEach(element => {
element();
});
}
}
function reject(error) {
if (self.status === 'pending') {
self.status = 'rejected'; //失败函数将其函数修改为rejected
self.error = error; //将失败的值保存起来
self.onErrorCallbacks.forEach(element => {
element();
})
}
}
executor(resolve, reject);
}
Promise.prototype.then = function (onResolved, onRejected) {
let self = this;
if (self.status === 'pending') {
self.onSuccessCallbacks.push(() => {
onResolved(self.success); //将resolve函数保留的成功值传递作为参数
})
self.onErrorCallbacks.push(() => {
onRejected(self.error); //将reject函数保留的失败值传递作为参数
})
}
if (self.status === 'resolved') {
onResolved(self.success); //将resolve函数保留的成功值传递作为参数
}
if (self.status === 'rejected') {
onRejected(self.error); //将reject函数保留的失败值传递作为参数
}
}
прецедент
let promise = new Promise((resolve, reject) => {
setTimeout(function () {
resolve('success data')
}, 2000)
})
promise.then(res => {
console.log("success:", res);
}, err => {
console.log("error:", err);
})
promise.then(res => {
console.log("success:", res);
}, err => {
console.log("error:", err);
})
Результат теста появится через 2 секунды
success: success data
success: success data
продолжайте попытки, если позволитеPromise
выдать ошибку как обращаться
let promise = new Promise((resolve, reject) => {
throw new error("一个错误");
})
promise.then(res => {
console.log("success:", res);
}, err => {
console.log("error:", err);
})
результат:
решать проблему
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
попробуйте еще раз, чтобы увидеть результаты
Результат модификации непосредственноexecutor
Функция обрабатывает исключения, а если возникает ошибка, напрямую входитreject
метод.
Выполнив вышеуказанный ряд улучшений, мы, наконец, достигаемPromise
цепные вызовы.
Promise
Для достижения цепных вызовов необходимо пройтиthen
метод возвращает новыйPromise
.
Если он возвращаетPromise
функция, то она будет ждать этогоPromise
После завершения выполнения вернитесь к следующемуthen
,Promise
Если получится, пойду в следующий разthen
успеха, в случае неудачи он перейдет к следующемуthen
с провал.
Уведомление:then
Функция обратного вызова, возвращаемая в методе, не может быть самой собой, если она написана так, то функция будет ждать своего выполнения.promise
В результате сформируется такое послойное состояние ожиданияад обратного звонка.
Далее пошаговый анализ (просто нужно улучшитьthen
функция)
then
вложенный в функциюnew Promise
Впоследствии в основномresolvePromise
функция, даx
Выносить суждения и предпринимать соответствующие действия:
На данный момент основные функции завершены, ниже приведены исходный код, примеры тестов и результаты.
Исходный код:
//Promise函数
function Promise(executor) {
let self = this; //保留this。防止后面方法出现this只想不明的问题
self.status = 'pending'; //promise的默认状态是pending
self.success = undefined; //保存成功回调传递的值
self.error = undefined; //保存失败回调传递的值
self.onSuccessCallbacks = []; //存放成功的回调
self.onErrorCallbacks = []; //存放失败的回调
function resolve(success) {
if (self.status === 'pending') {
self.status = 'resolved'; //成功函数将其状态修改为resolved
self.success = success; //将成功的值保存起来
self.onSuccessCallbacks.forEach(element => {
element();
});
}
}
function reject(error) {
if (self.status === 'pending') {
self.status = 'rejected'; //失败函数将其函数修改为rejected
self.error = error; //将失败的值保存起来
self.onErrorCallbacks.forEach(element => {
element();
})
}
}
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
//then函数
Promise.prototype.then = function (onResolved, onRejected) {
let self = this;
let promiseAgain = new Promise((resolve, reject) => {
if (self.status === 'pending') {
self.onSuccessCallbacks.push(() => {
let x = onResolved(self.success); //将resolve函数保留的成功值传递作为参数
resolvePromise(promiseAgain, x, resolve, reject);
})
self.onErrorCallbacks.push(() => {
let x = onRejected(self.error); //将reject函数保留的失败值传递作为参数
resolvePromise(promiseAgain, x, resolve, reject);
})
}
if (self.status === 'resolved') {
let x = onResolved(self.success); //将resolve函数保留的成功值传递作为参数
resolvePromise(promiseAgain, x, resolve, reject);
}
if (self.status === 'rejected') {
let x = onRejected(self.error); //将reject函数保留的失败值传递作为参数
resolvePromise(promiseAgain, x, resolve, reject);
}
})
return promiseAgain;
}
//resolvePromise函数
function resolvePromise(promiseAgain, x, resolve, reject) {
if (promiseAgain === x) {
return reject(new TypeError("循环调用"));
}
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, (y) => {
resolvePromise(promiseAgain, y, resolve, reject);
}, (e) => {
reject(e);
})
} else {
resolve(x);
}
} catch (error) {
reject(error);
}
} else {
resolve(x);
}
}
module.exports = Promise;
Пример теста:
let Promise = require('./Promise');
let promise = new Promise((resolve, reject) => {
setTimeout(function () {
resolve('success data')
}, 2000)
})
promise.then(res => {
console.log("第一次调用", res);
return res;
}, err => {
console.log("error:", err);
})
.then(res => {
console.log("第二次调用",res);
return res
}, err => {
console.log("err", err);
})
.then(res => {
console.log("第三次调用",res);
}, err => {
console.log("err", err);
})
Результаты теста:
第一次调用 success data
第二次调用 success data
第三次调用 success data
использовалPromise
, мы небрежно говоримPromise
это асинхронная функция, на самом делеPromise
в экземпляре (new
процесс) является синхронным, в то время какthen
Обратные вызовы, зарегистрированные в, выполняются асинхронно.
let Promise = require('./Promise');
let promise = new Promise((resolve, reject) => {
console.log("其次会被执行");
resolve("success data");
})
promise.then(res => {
console.log("第一次调用", res);
// return res;
}, err => {
console.log("error:", err);
})
console.log("首先会被执行");
Результаты:
其次会被执行
第一次调用 success data
首先会被执行
Окончательный код:
//Promise函数
function Promise(executor) {
let self = this; //保留this。防止后面方法出现this只想不明的问题
self.status = 'pending'; //promise的默认状态是pending
self.success = undefined; //保存成功回调传递的值
self.error = undefined; //保存失败回调传递的值
self.onSuccessCallbacks = []; //存放成功的回调
self.onErrorCallbacks = []; //存放失败的回调
function resolve(success) {
if (self.status === 'pending') {
self.status = 'resolved'; //成功函数将其状态修改为resolved
self.success = success; //将成功的值保存起来
self.onSuccessCallbacks.forEach(element => {
element();
});
}
}
function reject(error) {
if (self.status === 'pending') {
self.status = 'rejected'; //失败函数将其函数修改为rejected
self.error = error; //将失败的值保存起来
self.onErrorCallbacks.forEach(element => {
element();
})
}
}
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
//then函数
Promise.prototype.then = function (onResolved, onRejected) {
onResolved = typeof onResolved == 'function' ? onResolved : val => val;
onRejected = typeof onRejected == 'function' ? onRejected : err => {
throw err;
}
let self = this;
let promiseAgain = new Promise((resolve, reject) => {
if (self.status === 'pending') {
self.onSuccessCallbacks.push(() => {
try {
let x = onResolved(self.success); //将resolve函数保留的成功值传递作为参数
resolvePromise(promiseAgain, x, resolve, reject);
} catch (e) {
reject(e)
}
})
self.onErrorCallbacks.push(() => {
try {
let x = onRejected(self.error); //将reject函数保留的失败值传递作为参数
resolvePromise(promiseAgain, x, resolve, reject);
} catch (e) {
reject(e)
}
})
}
if (self.status === 'resolved') {
try {
let x = onResolved(self.success); //将resolve函数保留的成功值传递作为参数
resolvePromise(promiseAgain, x, resolve, reject);
} catch (e) {
reject(e)
}
}
if (self.status === 'rejected') {
try {
let x = onRejected(self.error); //将reject函数保留的失败值传递作为参数
resolvePromise(promiseAgain, x, resolve, reject);
} catch (e) {
reject(e)
}
}
})
return promiseAgain;
}
//resolvePromise函数
function resolvePromise(promiseAgain, x, resolve, reject) {
if (promiseAgain === x) {
return reject(new TypeError("循环调用"));
}
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, (y) => {
resolvePromise(promiseAgain, y, resolve, reject);
}, (e) => {
reject(e);
})
} else {
resolve(x);
}
} catch (error) {
reject(error);
}
} else {
resolve(x);
}
}
module.exports = Promise;
Пример теста:
let Promise = require('./Promise');
let promise = new Promise((resolve, reject) => {
setTimeout(function () {
resolve('success data')
}, 0)
})
promise.then(res => {
console.log("第一次调用", res);
return res;
}, err => {
console.log("error:", err);
})
.then(res => {
console.log("第二次调用",res);
return res
}, err => {
console.log("err", err);
})
.then(res => {
console.log("第三次调用",res);
}, err => {
console.log("err", err);
})
console.log("首先会被执行");
Результаты теста:
首先会被执行
第一次调用 success data
第二次调用 success data
第三次调用 success data
Эта статья только для моего собственного пониманияPromise
После исходного кода я написал его со своим пониманием, надеюсь, эта статья может быть полезной.
Наконец, я рекомендую читателям понятьPromise
, вы можете узнать о цикле событий браузера, который очень полезен для смешанныхsetTimeOut
,Promise
Порядок вывода очень полезен, вот рекомендуемая статьяЦикл событий на стороне браузера, а затем я мог бы также написать статью о цикле событий браузера.