иллюстрировать
Недавно я просматривал знание Promise, поэтому задал несколько вопросов, вот несколько вопросов, давайте посмотрим.
Тема 1
const promise = new Promise((resolve, reject) => {
console.log(1);
resolve();
console.log(2);
})
promise.then(() => {
console.log(3);
})
console.log(4);
Разобрать
Во-первых, Promise выполняется сразу после создания, поэтому сначала будут выведены 1, 2, аPromise.then()
Внутренний код выполняется сразу в конце текущего цикла обработки событий, поэтому он будет продолжать выводить 4 и, наконец, выводить 3.
Отвечать
1
2
4
3
тема вторая
const promise = new Promise((resolve, reject) => {
resolve('success1');
reject('error');
resolve('success2');
});
promise.then((res) => {
console.log('then:', res);
}).catch((err) => {
console.log('catch:', err);
})
Разобрать
resolve 函数
Измените состояние объекта Promise с“未完成”变为“成功”
(т.е. отpending 变为 resolved
), вызывается при успешном выполнении асинхронной операции, и результат асинхронной операции передается в качестве параметра;
reject 函数
Измените состояние объекта Promise с“未完成”变为“失败”
(т.е. отpending 变为 rejected
), вызываемый при сбое асинхронной операции, и передает сообщение об ошибке асинхронной операции в качестве параметра.
И как только состояние изменилось, оно уже никогда не изменится снова.
Итак, в кодеreject('error');
не будет работать.
Обещания могут разрешаться только один раз, а остальные вызовы игнорируются.
Итак, второй разresolve('success2');
тоже не будет работать.
Отвечать
then: success1
тема три
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
Разобрать
Promise.resolve
Параметр метода является примитивным значением или параметром, не имеющимthen
объект метода, затемPromise.resolve
метод возвращает новыйPromise
объект, состояниеresolved
,Promise.resolve
Одновременно в функцию обратного вызова будут переданы параметры метода.
then
Метод принимает функцию в качестве аргумента, и если ему не передана функция, он фактически интерпретирует ее какthen(null)
, что приводит к предыдущемуPromise
Результат проникнет ниже.
Отвечать
1
тема четвертая
Красный свет загорается раз в три секунды, зеленый свет — раз в секунду, а желтый свет — раз в 2 секунды; как сделать, чтобы три индикатора загорались попеременно и многократно? (реализовано с помощью Promse) Уже существуют три функции освещения:
function red() {
console.log('red');
}
function green() {
console.log('green');
}
function yellow() {
console.log('yellow');
}
Разобрать
Красный свет загорается один раз каждые три секунды, зеленый свет включается один раз в секунду, а желтый свет включается один раз каждые 2 секунды, что означает, что в течение 3 секунд красная функция выполняется один раз, зеленая функция выполняется один раз. за 2 секунды желтая функция выполняется один раз в 1 секунду, а огни повторяются попеременно и неоднократно Это означает, что три функции всегда выполняются в этом порядке, и этот шаг может быть реализован рекурсией.
Отвечать
function red() {
console.log('red');
}
function green() {
console.log('green');
}
function yellow() {
console.log('yellow');
}
var light = function (timmer, cb) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
cb();
resolve();
}, timmer);
});
};
var step = function () {
Promise.resolve().then(function () {
return light(3000, red);
}).then(function () {
return light(2000, green);
}).then(function () {
return light(1000, yellow);
}).then(function () {
step();
});
}
step();
пятая тема
Реализуйте функцию mergePromise, последовательно выполняйте переданные массивы и последовательно помещайте возвращенные данные в данные массива.
const timeout = ms => new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, ms);
});
const ajax1 = () => timeout(2000).then(() => {
console.log('1');
return 1;
});
const ajax2 = () => timeout(1000).then(() => {
console.log('2');
return 2;
});
const ajax3 = () => timeout(2000).then(() => {
console.log('3');
return 3;
});
const mergePromise = ajaxArray => {
// 在这里实现你的代码
};
mergePromise([ajax1, ajax2, ajax3]).then(data => {
console.log('done');
console.log(data); // data 为 [1, 2, 3]
});
// 要求分别输出
// 1
// 2
// 3
// done
// [1, 2, 3]
Разобрать
первыйajax1 、ajax2、ajax3
Все они являются функциями, но после выполнения этих функций они возвращаютPromise
, согласно требованиям заголовка, нам достаточно последовательно выполнить эти три функции, а затем поместить результаты вdata
Во, но эти функции находятся в асинхронной работе, вы хотите выполнить заказ, тогда выход не так прост, как 1, 2, посмотрите пример.
function A() {
setTimeout(function () {
console.log('a');
}, 3000);
}
function B() {
setTimeout(function () {
console.log('b');
}, 1000);
}
A();
B();
// b
// a
В примере мы выполняем последовательноA
,B
Но выходb
,a
Для этих асинхронных функций одна не будет выполняться по порядку, а затем будет выполняться следующая.
Этот вопрос для экзаменаPromise
Чтобы управлять асинхронным процессом, нам нужно найти способ позволить этим функциям после выполнения одной выполнять следующую и видеть ответ.
Отвечать
// 保存数组中的函数执行后的结果
var data = [];
// Promise.resolve方法调用时不带参数,直接返回一个resolved状态的 Promise 对象。
var sequence = Promise.resolve();
ajaxArray.forEach(function (item) {
// 第一次的 then 方法用来执行数组中的每个函数,
// 第二次的 then 方法接受数组中的函数执行后返回的结果,
// 并把结果添加到 data 中,然后把 data 返回。
// 这里对 sequence 的重新赋值,其实是相当于延长了 Promise 链
sequence = sequence.then(item).then(function (res) {
data.push(res);
return data;
});
})
// 遍历结束后,返回一个 Promise,也就是 sequence, 他的 [[PromiseValue]] 值就是 data,
// 而 data(保存数组中的函数执行后的结果) 也会作为参数,传入下次调用的 then 方法中。
return sequence;
тема шесть
Каков окончательный результат следующего кода?
const first = () => (new Promise((resolve, reject) => {
console.log(3);
let p = new Promise((resolve, reject) => {
console.log(7);
setTimeout(() => {
console.log(5);
resolve(6);
}, 0)
resolve(1);
});
resolve(2);
p.then((arg) => {
console.log(arg);
});
}));
first().then((arg) => {
console.log(arg);
});
console.log(4);
Разобрать
Этот вопрос на самом делеPromise
Отношения не слишком большие, в основном потому, что вам нужно понимать механизм выполнения JS, чтобы хорошо решить эту проблему.Друзья, которые не понимают механизм выполнения JS, рекомендуют прочитать эту статью.
На этот раз досконально изучите механизм выполнения JavaScript.
Первый раунд цикла событий
Сначала выполните задачу макроса, основной скрипт, новое обещание будет выполнено немедленно и выведет [3],
Выполните новую операцию Promise p и выведите [7],
Нашел setTimeout, поместил обратный вызов в следующий раунд очереди задач (Event Queue), p's then, назовем его then1, поместил его в очередь микрозадач, нашел первый then, вызвал then2, поместил его в микрозадачу очередь. воплощать в жизньconsole.log(4)
, вывод [4], выполнение макрозадачи завершается.
Затем выполните микрозадачу, выполните then1 и выведите [1],
Выполните then2 и выведите [2].
В этот момент заканчивается первый раунд цикла событий. Начать второй раунд.
Второй раунд цикла событий
Сначала выполните задачу макроса, то есть обратный вызов setTimeout, и выведите [5].
resolve(6)
Это не вступит в силу, потому что состояние Promise p не изменится после его изменения.
Отвечать
3
7
4
1
2
5
тема семь
Есть 8 URL-адресов ресурсов изображений, уже сохраненных в массиве.urls
среда (т.е.urls = ['http://example.com/1.jpg', ...., 'http://example.com/8.jpg'])
, а функция уже естьfunction loadImg
, введите URL-ссылку, верните обещание, обещание разрешается, когда загрузка изображения завершена, и отклоняется, когда загрузка не удалась.
Однако мы требуем, чтобы в любой момент времени количество загружаемых одновременно ссылок не превышало 3.
Пожалуйста, напишите фрагмент кода для выполнения этого требования, требующего, чтобы все изображения загружались как можно быстрее.
var urls = ['https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg', 'https://www.kkkk1000.com/images/getImgData/gray.gif', 'https://www.kkkk1000.com/images/getImgData/Particle.gif', 'https://www.kkkk1000.com/images/getImgData/arithmetic.png', 'https://www.kkkk1000.com/images/getImgData/arithmetic2.gif', 'https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg', 'https://www.kkkk1000.com/images/getImgData/arithmetic.gif', 'https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/10/29/166be40ccc434be0~tplv-t2oaga2asx-image.image'];
function loadImg(url) {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = function () {
console.log('一张图片加载完成');
resolve();
}
img.onerror = reject
img.src = url
})
};
Разобрать
Смысл заголовка в том, что нам нужно сделать это, сначала запросить 3 изображения одновременно, когда одно изображение загружено, оно будет продолжать инициировать запрос на изображение, так что количество параллелизма сохраняется на уровне 3, пока все Инициируются загружаемые изображения.
Реализация обещаний заключается в одновременном запросе 3 ресурсов изображения, чтобы вы могли получить 3 обещания и сформировать массив, который называетсяpromises
Ну а потом продолжай звонитьPromise.raceчтобы вернуть обещание, состояние которого изменяется быстрее всего, а затем получить обещание из массива (promises
), удалите объект Promise и добавьте новый Promise, пока не будут получены все URL-адреса, а затем снова используйте его.Promise.allдля обработки массива один раз (promises
) без промисов, изменяющих состояние.
Отвечать
var urls = ['https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg', 'https://www.kkkk1000.com/images/getImgData/gray.gif', 'https://www.kkkk1000.com/images/getImgData/Particle.gif', 'https://www.kkkk1000.com/images/getImgData/arithmetic.png', 'https://www.kkkk1000.com/images/getImgData/arithmetic2.gif', 'https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg', 'https://www.kkkk1000.com/images/getImgData/arithmetic.gif', 'https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/10/29/166be40ccc434be0~tplv-t2oaga2asx-image.image'];
function loadImg(url) {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = function () {
console.log('一张图片加载完成');
resolve();
}
img.onerror = reject
img.src = url
})
};
function limitLoad(urls, handler, limit) {
// 对数组做一个拷贝
const sequence = [].concat(urls)
let promises = [];
//并发请求到最大数
promises = sequence.splice(0, limit).map((url, index) => {
// 这里返回的 index 是任务在 promises 的脚标,用于在 Promise.race 之后找到完成的任务脚标
return handler(url).then(() => {
return index
});
});
// 利用数组的 reduce 方法来以队列的形式执行
return sequence.reduce((last, url, currentIndex) => {
return last.then(() => {
// 返回最快改变状态的 Promise
return Promise.race(promises)
}).catch(err => {
// 这里的 catch 不仅用来捕获 前面 then 方法抛出的错误
// 更重要的是防止中断整个链式调用
console.error(err)
}).then((res) => {
// 用新的 Promise 替换掉最快改变状态的 Promise
promises[res] = handler(sequence[currentIndex]).then(() => { return res });
})
}, Promise.resolve()).then(() => {
return Promise.all(promises)
})
}
limitLoad(urls, loadImg, 3)
/*
因为 limitLoad 函数也返回一个 Promise,所以当 所有图片加载完成后,可以继续链式调用
limitLoad(urls, loadImg, 3).then(() => {
console.log('所有图片加载完成');
}).catch(err => {
console.error(err);
})
*/
Суммировать
Некоторые из этих вопросов проверяют базовые знания промисов, а некоторые проверяют гибкое использование промисов.Если вы хорошо ответите на все эти вопросы, то ваше понимание промисов должно быть хорошим.
Наконец, если в тексте есть недостатки или ошибки, пожалуйста, укажите на мелких партнеров, большое спасибо. Если вам кажется, что содержания статьи недостаточно, в конце есть статья по теме, можете ее прочитать.
Ссылаться на
Начало работы с ECMAScript 6 — Руан Ифэн
Давайте поговорим об обещаниях в серии ES6.
Вопрос интервью о приложении Promise
Вопросы по интерфейсному тесту Ali — понимание и применение функции Promise в ES6
На этот раз досконально изучите механизм выполнения JavaScript.
Введение во все методы нативного Promise ES6 (с темой сценария приложения)