Упрощая / развивая ответ Ника Сотироса (который я считаю удивительным), я думаю, что лучше всего описать, как можно начать кодирование с yield
.
На мой взгляд, самое большое преимущество использования yield
состоит в том, что оно устранит все проблемы с вложенными обратными вызовами, которые мы видим в коде. Трудно понять, как сначала, поэтому я решил написать этот ответ (для себя и, надеюсь, других!)
То, как это происходит, заключается в представлении идеи сопрограммы, которая является функцией, которая может добровольно останавливаться / останавливаться, пока не получит то, что ей нужно. В javascript это обозначено function*
. Только function*
функции могут использовать yield
.
Вот типичный JavaScript:
loadFromDB('query', function (err, result) {
// Do something with the result or handle the error
})
Это неуклюже, потому что теперь весь ваш код (который, очевидно, должен ждать этого вызова loadFromDB
) должен находиться внутри этого уродливого обратного вызова. Это плохо по нескольким причинам ...
- Весь ваш код имеет отступ на один уровень в
- У вас есть этот конец
})
, который нужно отслеживать везде
- Все это дополнительно
function (err, result)
жаргон
- Не совсем понятно, что вы делаете это, чтобы присвоить значение
result
С другой стороны, с помощью yield
все это можно сделать в одной строке с помощью симпатичного сопрограммного фреймворка.
function* main() {
var result = yield loadFromDB('query')
}
И теперь ваша основная функция будет выдавать, где это необходимо, когда ей нужно ждать загрузки переменных и вещей. Но теперь, чтобы запустить это, вам нужно вызвать normal (функция без сопрограмм). Простая сопрограммная среда может решить эту проблему, так что все, что вам нужно сделать, это запустить:
start(main())
И начало определено (из ответа Ника Сотиро)
function start(routine, data) {
result = routine.next(data);
if(!result.done) {
result.value(function(err, data) {
if(err) routine.throw(err); // continue next iteration of routine with an exception
else start(routine, data); // continue next iteration of routine normally
});
}
}
И теперь у вас может быть красивый код, который гораздо более читабелен, легко удаляется, и вам не нужно возиться с отступами, функциями и т. Д.
Интересное наблюдение состоит в том, что в этом примере yield
на самом деле является просто ключевым словом, которое вы можете поместить перед функцией с обратным вызовом.
function* main() {
console.log(yield function(cb) { cb(null, "Hello World") })
}
Будет напечатано "Hello World". Таким образом, вы можете превратить любую функцию обратного вызова в использование yield
, просто создав одну и ту же сигнатуру функции (без cb) и вернув function (cb) {}
, например:
function yieldAsyncFunc(arg1, arg2) {
return function (cb) {
realAsyncFunc(arg1, arg2, cb)
}
}
Надеемся, что благодаря этим знаниям вы сможете написать более понятный и читаемый код, который легко удалить !