Извините, интервьюер! Наконец-то я добрался до Обещания...

опрос

предисловие

Xiaobaicai также хотел найти стажировку на переднем крае, поэтому он встретился. Позвольте мне сначала поделиться с вами всеми вопросами.

вопросы интервью

  • CSS реализует горизонтальное и вертикальное центрирование
  • свойства флекса
  • Эффект реализации и свойства перехода CSS
  • CSS реализует вращение на 360 градусов по оси Y.
  • Хорошо, какие основные типы данных JS и каковы суждения?
  • Как оценить массив
  • Разница между ссылочными типами и примитивными типами
  • Что такое стек? Что такое куча?
  • рукописный флип-строка
  • Аргумент рукописной суммы (1,2,3)
  • Разница между стрелочными функциями и обычными функциями (забыл аргумент в вопросе выше, интервьюер задал этот вопрос специально, чтобы напомнить мне, что фундамент слишком плохой, чтобы экономить... слезы)
  • Метод дедупликации массива
  • Ленивая загрузка изображения
  • Причина междоменной генерации, что такое политика одного и того же происхождения
  • Расскажите о решении, которое вы знаете (только JSONP и CORS)
  • Разница между файлами cookie, sessionStorage и localStorage
  • Разница между get и post (отличается только способ передачи параметров и функций, интервьюер спросил, есть ли другие...)
  • Спросили о проекте, отреагируйте
  • Понимание ES6 (от Promise действительно никуда не деться....)
  • Разница между пусть var const
  • Знаешь обещания? Расскажите о своем понимании Promise? (Говорят, что объект Promise представляет собой асинхронную операцию, есть три состояния, состояние меняется на одностороннее...)
  • Так какую проблему он решает? (эммм, когда асинхронному возвращаемому значению нужно дождаться другого асинхронного, обратный вызов будет вложенным. Обещание может решить эту проблему ада обратного вызова)
  • Итак, как это решает ад обратного вызова? (Внутренняя часть объекта Promise является синхронной, и после получения внутреннего значения вызывается асинхронная операция .then, которая всегда может быть .then .then...)
  • Ну, вы сказали, что можете .тогда .тогда все время... так как же он достигает .тогда все время? (эммм... это .тогда цепной звонок... это...)
  • Каковы методы Обещания?В чем разница между всеми и расой?
  • В частности, .catch() и reject (... я оцепенел...)

завершить сеанс

  • Я спросил интервьюера о понимании CSS (необходимо, но не важно, суть интерфейса — попытаться восстановить черновик дизайна один за другим, а взаимодействие можно рассматривать только тогда, когда страница написана)

  • как научиться

  • Как вы прошли через этот процесс (выполняйте больше проектов, научитесь понимать каждую деталь в проекте, еще раз напомните мне о важности основ)

Обзор промисов

Promise — это новый ссылочный тип в ES6, и объекты можно создавать с помощью new. Обещания содержат асинхронные операции внутри.

new Promise(fn)

Promise.resolve(fn)

В любом случае вернет объект обещания.

  • Обещания имеют три состояния:В ожидании, выполнено и отклонено, а Promise должен быть одним из трех состояний.Только результат асинхронной операции может определить, какое состояние находится в данный момент, и никакая другая операция не может изменить это состояние.
  • Статус можно изменить только с «Ожидание» на «Выполнено» или «Ожидание» на «Отклонено»., и состояние не изменится после изменения состояния, оно сохранит это состояние навсегда.
  • Ожидание становится выполненным и получает приватноеvalue, Pending становится Rejected, получит частныйreason, когда Promise достигает Fulfilled или Rejected, исполняемый асинхронный код получит это значение или причину.

Зная это, мы можем получить следующий код:

Принцип реализации

class Promise {
    constructor() {
        this.state = 'pending'  // 初始化 未完成状态 
        // 成功的值
        this.value = undefined;
        // 失败的原因
        this.reason = undefined;
    }
}

Основное использование

Состоянием промиса можно управлять только внутри, а внутренние операции выполняются в функции-исполнителе промиса. Обещание должно принимать функцию в качестве параметра, мы называем эту функцию функцией-исполнителем, а функция-исполнитель содержит два параметра, разрешение и отклонение, которые являются двумя функциями.

  • разрешить : изменить состояние объекта Promise с Pending (в процессе) на Fulfilled (успешно)
  • Отклонить: изменить состояние объекта обещания от ожидания (в процессе), чтобы отклонить (не удалось) и бросить ошибку.

использовать каштаны

let p1 = new Promise((resolve,reject) => {
    resolve(value);
})
setTimeout(() => {
    console.log((p1)); // Promise {<fulfilled>: undefined}
},1)   

let p2 = new Promise((resolve,reject) => {
    reject(reason);
})
setTimeout(() => {
    console.log((p2)); // Promise {<rejected>: undefined}
},1) 

Принцип реализации

  • p1 разрешается как успешный, получает значение параметра, и статус меняется на выполненный, который нельзя изменить снова.
  • p2 reject — сбой, параметр Reason получен, и состояние изменено на reject, которое нельзя изменить снова.
  • Если выполнение функции executor executor сообщает об ошибке, выполните команду reject напрямую.

Таким образом, для получения следующего кода:

class Promise{
    constructor(executor){
      // 初始化state为等待态
      this.state = 'pending';
      // 成功的值
      this.value = undefined;
      // 失败的原因
      this.reason = undefined;
      let resolve = value => {
         console.log(value);
        if (this.state === 'pending') {
          // resolve调用后,state转化为成功态
          console.log('fulfilled 状态被执行');
          this.state = 'fulfilled';
          // 储存成功的值
          this.value = value;
        }
      };
      let reject = reason => {
         console.log(reason);
        if (this.state === 'pending') {
          // reject调用后,state转化为失败态
          console.log('rejected 状态被执行');
          this.state = 'rejected';
          // 储存失败的原因
          this.reason = reason;
        }
      };
      // 如果 执行器函数 执行报错,直接执行reject
      try{
        executor(resolve, reject);
      } catch (err) {
        reject(err);
      }
    }
  }

Проверьте вышеуказанный код:

class Promise{...} // 上述代码

new Promise((resolve, reject) => {
    console.log(0);
    setTimeout(() => {
        resolve(10) // 1
        // reject('JS我不爱你了') // 2
        // 可能有错误
        // throw new Error('是你的错') // 3    
    }, 1000)
})
  • При выполнении кода 1 вывод0вывод в следующую секунду10а такжестатус выполнен;
  • При выполнении кода 2 вывод0вывод в следующую секундуя больше не люблю тебяа такжеОтклоненное состояние выполняется
  • При выполнении кода 3 выдает ошибкуэто твоя ошибка

.тогда метод

promise.then(onFulfilled, onRejected)

  • Когда промис инициализируется, функция-исполнитель изменила состояние промиса. И функция-исполнитель выполняется синхронно. Данные, возвращаемые асинхронной операцией (значение успеха и причина неудачи), могут быть переданы в .then для предоставления обработчика экземпляра Promise.
  • После создания экземпляра Promise вы можете использовать метод then, чтобы указать его отдельно.разрешенное состояниеа такжеотклоненный статусфункция обратного вызова. эти две функцииonFulfilled,onRejectedОба являются необязательными и не должны предоставляться. Если указано, обещание идет отдельноразрешенное состояниеа такжеотклоненный статуспри исполнении.
  • и все, что передается методу thenпараметр нефункционального типамолча игнорируются.
  • то метод должен возвращатьновый объект обещания(Ключ к реализации связанных вызовов)

Принцип реализации

  • Промисы могут переходить в конечное состояние только один раз, поэтомуonFulfilledа такжеonRejectedОперация с двумя аргументамивзаимоисключающийиз
  • когда государствоfulfilled, затем выполнитеonFulfilled, входящийthis.value. когда государствоrejected, затем выполнитеonRejected, входящийthis.reason
class Promise {
    constructor(executor) {
        this.state = 'pending'  // 初始化 未完成状态 
        // 成功的值
        this.value = undefined;
        // 失败的原因
        this.reason = undefined;

        // .then 立即执行后 state为pengding  把.then保存起来
        this.onResolvedCallbacks = [];
        this.onRejectedCallbacks = [];

        // 把异步任务 把结果交给 resolve
        let resolve = (value) => {
            if (this.state === 'pending') {
                console.log('fulfilled 状态被执行');
                this.value = value
                this.state = 'fulfilled'
                // onFulfilled 要执行一次
                this.onResolvedCallbacks.forEach(fn => fn());
            }
        }
        let reject = (reason) => {
            if (this.state === 'pending') {
                console.log('rejected 状态被执行');
                this.reason = reason
                this.state = 'rejected'
                this.onRejectedCallbacks.forEach(fn => fn());
            }
        }
        try {
            executor(resolve, reject)
        }
        catch (e) {
            reject(err)
        }
    }
    // 一个promise解决了后(完成状态转移,把控制权交出来)
    then(onFulfilled, onRejected) {
        if (this.state == 'pending') {
            this.onResolvedCallbacks.push(() => {
                onFulfilled(this.value)
            })
            this.onRejectedCallbacks.push(() => {
                onRejected(this.reason)
            })
        }
        console.log('then');
        // 状态为fulfilled  执行成功  传入成功后的回调  把执行权转移
        if (this.state == 'fulfiiied') {
            onFulfilled(this.value);
        }
        // 状态为rejected 执行失败  传入失败后的回调  把执行权转移
        if (this.state == 'rejected') {
            onRejected(this.reason)
        }
    }
}
let p1 = new Promise((resolve, reject) => {
    console.log(0);
    setTimeout(() => {      
        // resolve(10)
        reject('JS我不爱你了')
        console.log('setTimeout');    
    }, 1000)
}).then(null,(data) => {
    console.log(data, '++++++++++');
})
0
then
rejected 状态被执行
JS我不爱你了 ++++++++++
setTimeout

Когда разрешение выполняется в setTomeout, состояние все еще находится в состоянии ожидания.Нам нужно сохранить успех и неудачу в соответствующих массивах, когда затем вызывается, и вызывать их после отклонения или разрешения.

Теперь вы можете асинхронно, но все равно нельзя приковать, чтобы позвонить ах? Чтобы выполнить функцию, затем привязанные звонки,затем необходимо вернуть экземпляр обещания, а затем передать значение, возвращаемое этим промисом, в следующее then.

Цепной вызов и последующая реализация исходного кода

Я не пойму эту часть, я не понял. Последующий. Сначала поместите код:

class Promise{
  constructor(executor){
    this.state = 'pending';
    this.value = undefined;
    this.reason = undefined;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    let resolve = value => {
      if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.value = value;
        this.onResolvedCallbacks.forEach(fn=>fn());
      }
    };
    let reject = reason => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn=>fn());
      }
    };
    try{
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }
  then(onFulfilled,onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
    let promise2 = new Promise((resolve, reject) => {
      if (this.state === 'fulfilled') {
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      };
      if (this.state === 'rejected') {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      };
      if (this.state === 'pending') {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0)
        });
      };
    });
    return promise2;
  }
  catch(fn){
    return this.then(null,fn);
  }
}
function resolvePromise(promise2, x, resolve, reject){
  if(x === promise2){
    return reject(new TypeError('Chaining cycle detected for promise'));
  }
  let called;
  if (x != null && (typeof x === 'object' || typeof x === 'function')) {
    try {
      let then = x.then;
      if (typeof then === 'function') { 
        then.call(x, y => {
          if(called)return;
          called = true;
          resolvePromise(promise2, y, resolve, reject);
        }, err => {
          if(called)return;
          called = true;
          reject(err);
        })
      } else {
        resolve(x);
      }
    } catch (e) {
      if(called)return;
      called = true;
      reject(e); 
    }
  } else {
    resolve(x);
  }
}
//resolve方法
Promise.resolve = function(val){
  return new Promise((resolve,reject)=>{
    resolve(val)
  });
}
//reject方法
Promise.reject = function(val){
  return new Promise((resolve,reject)=>{
    reject(val)
  });
}
//race方法 
Promise.race = function(promises){
  return new Promise((resolve,reject)=>{
    for(let i=0;i<promises.length;i++){
      promises[i].then(resolve,reject)
    };
  })
}
//all方法(获取所有的promise,都执行then,把结果放到数组,一起返回)
Promise.all = function(promises){
  let arr = [];
  let i = 0;
  function processData(index,data){
    arr[index] = data;
    i++;
    if(i == promises.length){
      resolve(arr);
    };
  };
  return new Promise((resolve,reject)=>{
    for(let i=0;i<promises.length;i++){
      promises[i].then(data=>{
        processData(i,data);
      },reject);
    };
  });
}

Заинтересованные друзья могут двигаться

Ссылаться на

Различные методы промисов

Promise.prototype.catch()

Функция обработчика исключений catch обрабатывает исключения, которые могут быть вызваны предыдущим обратным вызовом. принимает только один параметрonRejectedобработчик. Это эквивалентно вызову Promise.prototype.then(null, onRejected), поэтомутакже возвращает новое обещание

  • каштан
let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(10)  
    }, 1000)
}).then(() => {
       throw Error("1123")
}).catch((err) => {
    console.log(err);
})
.then(() => {
    console.log('异常捕获后可以继续.then');
})

Выполнение может быть продолжено после перехвата первого исключения .then.

Promise.all()

Промис, созданный с помощью Promise.all(), будет разрешен после того, как будет разрешен весь набор промисов. Другими словами, он будет ждать, пока все обещанные программы вернут результаты, а затем выполнять последующие программы. Возвращает новое обещание.

  • каштан
let p1 = new Promise((resolve, reject) => {  
    resolve('success1')
})

let p2 = new Promise((resolve, reject) => {  
    resolve('success1')
})
// let p3 = Promise.reject('failed3')
Promise.all([p1, p2]).then((result) => {  
    console.log(result)   // ['success1', 'success2']             
    
}).catch((error) => {  
    console.log(error)
})
// Promise.all([p1,p3,p2]).then((result) => {  
//     console.log(result)
// }).catch((error) => {  
//     console.log(error) //  'failed3'     
//     
// })

С полученным выше каштаном все свойства:

  • Если все успешно, возвращаемое значение составного промиса представляет собой массив возвращаемых значений всех дочерних промисов.
  • Если один из них терпит неудачу, первый из них будет использовать свою собственную причину как причину сбоя составного промиса.

Promise.race()

Promise.race() возвращает новое обещание с первым разрешенным или первым отклоненным обещанием в наборе.

  • каштан
let p1 = new Promise((resolve, reject) => {  
    setTimeout(() => {    
        resolve('success1')  
    },1000)
})

let p2 = new Promise((resolve, reject) => {  
    setTimeout(() => {    
        reject('failed2')  
    }, 1500)
})

Promise.race([p1, p2]).then((result) => {  
    console.log(result)
}).catch((error) => {  
    console.log(error)  //  'success1'    
})

С полученным выше каштаном свойства расы:

  • В любом случае первое завершение выполнения выполняет соответствующее последующее .then или .catch. Тот, кто в качестве обратного вызова

Суммировать

Вышеупомянутое обещание кратко изложено здесь. Это может быть не очень ясно. Заинтересованные друзья могут посмотреть ссылку. Если у вас есть какое-то понимание, вы можете обменяться мнениями и учиться вместе в области комментариев ниже.

Интервью закончилось, интервьюер очень милый, и разговор очень приятный.Вопросы, наверное, можно сказать немного, но всегда есть ключевые моменты, которые были забыты ххххх.В конце я поболтал с интервьюером и легко забыть этот вопрос, хахахаха он сказал я забыл это просто я не выучил его, так что мне еще нужно подвести итоги и сделать больше проектов в будущем...

Интервью могут помочь вам обнаружить больше пробелов в знаниях, тем самым способствуя вашему собственному обучению. Давайте усердно работать вместе! !