Я обнаружил, что во многих блогах параллельное / неблокирующее / асинхронное программирование упоминается как преимущество стиля продолжения передачи (CPS). Я не могу понять, почему CPS обеспечивает параллелизм, например, люди упоминают, что Node.js реализован с использованием CPS, хотя JavaScript является синхронным языком. Кто-нибудь прокомментирует мои мысли?
Во-первых, мое наивное понимание CPS таково, что обертывание всего последующего кода в точке в функцию и явная передача этой функции в качестве параметра. Некоторые блоги называют функцию продолжения return(), Габриэль Гонсалес называет ее отверстие, и оба эти объяснения являются блестящими.
Мое замешательство в основном связано с популярной статьей в блоге Асинхронное программирование и стиль передачи продолжения в JavaScript. В начале статьи доктор Аксель Раушмайер приводит два фрагмента кода, синхронную программу и асинхронную программу на CPS (вставлены сюда для удобства чтения).
Синхронный код:
function loadAvatarImage(id) {
var profile = loadProfile(id);
return loadImage(profile.avatarUrl);
}
Асинхронный код:
function loadAvatarImage(id, callback) {
loadProfile(id, function (profile) {
loadImage(profile.avatarUrl, callback);
});
}
Я не понимаю, почему CPS асинхронный. После того, как я прочитал другую статью На примере: стиль передачи продолжения в JavaScript, я подумал, что, возможно, в коде есть предположение: функции loadProfile() и loadImage() сами по себе являются асинхронными функциями. Тогда это не CPS делает его асинхронным. В вторая статья автор фактически показывает реализацию fetch(), которая похожа на loadProfile() в блоге ранее. Функция fetch() делает явное предположение о базовой модели параллельного выполнения, вызывая req.onreadystatechange. Это наводит меня на мысль, что, возможно, параллелизм обеспечивается не CPS.
Предположим, что базовые функции асинхронны, тогда я перехожу ко второму вопросу: можем ли мы писать асинхронный код без CPS? Подумайте о реализации функции loadProfile(). Если это асинхронно не из-за CPS, почему мы не можем просто использовать тот же механизм для асинхронной реализации loadAvatarImage()? Предположим, что loadProfile() использует fork() для создания нового потока для отправки запроса и ожидания ответа, пока основной поток выполняется неблокирующим образом, мы можем сделать то же самое для loadAvatarImage().
function loadAvatarImage(id, updateDOM) {
function act () {
var profile = loadProfile(id);
var img = loadImage(profile.avatarUrl);
updateDOM (img);
}
fork (act());
}
Я даю ему функцию обратного вызова updateDOM(). Без updateDOM() было бы несправедливо сравнивать его с версией CPS - версия CPS содержит дополнительную информацию о том, что делать после загрузки изображения, то есть функцию callback, а исходный синхронный loadAvatarImage() - нет.
Интересно, что @DarthFennec указал, что мой новый loadAvatarImage() на самом деле является CPS: fork() - это CPS, act() - это CPS (если мы явно укажем ему updateDOM), а loadAvatarImage() - это CPS. Цепочка делает loadAvatarImage() асинхронным. loadProfile() и loadImage() не обязательно должны быть асинхронными или CPS.
Если рассуждения, приведенные здесь, верны, могу ли я сделать эти два вывода?
loadProfile(), loadImage(), fetch() или fork(), то можно кодировать только в стиле CPS, чтобы гарантировать, что асинхронные API-интерфейсы используются асинхронно, например, return loadImage(profile.avatarUrl) аннулирует параллелизм loadImage().Отличный улов, @DarthFennec! Я никогда не думал, что fork() - это CPS, а на самом деле loadAvatarImage() - это CPS. Интересно. Позвольте мне немного отредактировать вопрос, чтобы вы могли написать свой ответ формально. Спасибо, что помогли мне понять это немного больше!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


«Важный момент: это не CPS - loadProfile () и loadImage () не являются функциями CPS». Я не уверен, что вы имеете в виду.
loadAvatarImageявляется CPS в вашем примере. Конечно,loadProfileиloadImageне работают одновременно или CPS. Ноforkодновременно работает и CPS. И посколькуforkобеспечивает асинхронность через CPS,loadAvatarImageтакже должен. Если бы здесьloadAvatarImageне был CPS, он не был бы асинхронным.