Javascript: цепочка обещаний против асинхронных / ожидающих? - PullRequest
0 голосов
/ 08 мая 2018

Я узнаю о Javascript Promise и async / await. Приведенный ниже пример кода асинхронно считывает и анализирует файл JSON в файле node.js ( my node.js версия v10.0.0 ).

В примере кода функция ChainReadJson и функция AwaitReadJson выполняют одно и то же, читая и анализируя файл JSON. Разница в том, что функция ChainReadJson использует цепочку обещаний, а функция AwaitReadJson - async / await.

const FS = require("fs");

function ReadFile(fileName) {
    return new Promise((Resolve, Reject) => {
        FS.readFile(fileName, 'utf8', (error, result) => {
            if (error)
                Reject(error);
            else
                Resolve(result);
        });
    });
}

// function using promise chain

function ChainReadJson(fileName, CallBack) {
    ReadFile(fileName)
        .then(
            res => JSON.parse(res),
            err => {
                Message(-1, err.message);
            }
        )
        .then(
            res => {
                if (res !== undefined)
                    CallBack(fileName, res);
            },
            err => {
                Message(-2, err.message);
            }
        );
}

// function using async/await

async function AwaitReadJson(fileName, CallBack) {
    let res, json;

    try {
        res = await ReadFile(fileName);
    }
    catch (err) {
        Message(-1, err.message);
        return;
    }
    try {
        json = JSON.parse(res);
    }
    catch (err) {
        Message(-2, err.message);
        return;
    }
    CallBack(fileName, json);
}

ChainReadJson('test.json', PrintJSON);
AwaitReadJson('test.json', PrintJSON);

// common functions

function PrintJSON(fileName, json) {
    console.log(`JSON[${fileName}]:`, json);
}

function Message(n, str) {
    console.log(`[${n}]`, str);
}

При написании кода для функции ChainReadJson с использованием цепочки обещаний у меня возникли трудности с контролем результатов выполнения и ошибок.
Однако при написании кода для функции AwaitReadJson с использованием async / await эти трудности в основном исчезают.

Правильно ли я понимаю преимущества async / await? Каковы недостатки async / await по сравнению с цепочкой обещаний?

(Пример кода является модифицированной версией кода в этом ответе . Оригинальный код использует только цепочку обещаний и написан, чтобы точно знать, где в цепочке произошла ошибка и что является ошибкой )

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Хотя async/await может быть хорошим способом очистки асинхронной логики, стоит отметить, что логику обещаний можно значительно очистить, вплоть до того, что она очень похожа на альтернативу async / await:

const fs = require("fs");
const util = require("util")

//Could also use the experimental "fs/promise" api from node v10
const promisifiedReadFile = util.promisify(fs.readFile);

const readFile = (fileName) => promisifiedReadFile(fileName, 'utf8');

function chainReadJson(fileName, callback) {
    return readFile(fileName)
        .then(json => JSON.parse(json))
        .then(result => callback(null, result))
        .catch(e => {
            console.log("Error reading or parsing file", e.message);
            callback(e)
        });
}

Единственное функциональное отличие здесь состоит в том, что вся регистрация ошибок происходит в одном месте, в конце цепочки.

Можно сохранить ведение журнала разделения для readFile и JSON.parse, но это немного сложнее. Как правило, вы хотите повторно генерировать ошибки после их обработки, чтобы нисходящие обработчики .then были пропущены: но если вы снова выбросите ошибку, она будет снова перехвачена нижестоящими обработчиками .catch, что приведет к дублированию регистрации , если вы не нашли способ отфильтровать его.

Это выполнимо, но это немного больно, поэтому я оставил это вне приведенного выше кода.

0 голосов
/ 08 мая 2018

Действительно, async/await были предназначены для сокращения шаблонов и облегчения написания асинхронных программ по сравнению с обратными вызовами, обещаниями и функциями генератора.

  • Пока создавались обещанияс той же целью у них было дополнительное ограничение для работы в существующих механизмах JS - поэтому их синтаксис более сложный. Для использования async / await требуется относительно новый JS-движок . Возможно, это не имеет значения, если вы пишете собственное приложение для node.js, но библиотека должна быть совместима сБолее старые версии node.js (и я не уверен, что вы можете перенести его для использования в старых браузерах без поддержки генератора).
  • Поскольку async / await новее, не так оптимизирован ,Сравнение, проведенное в прошлом году , сообщает Обещания Bluebird (библиотека JS, реализующая упрощенную версию обещаний) опережает async / await в определенном тесте.(Конечно, это может не иметь значения, когда ваш сценарий использования делает несколько сетевых запросов.)
  • Возможно, вам все еще потребуются обещания для выполнения нескольких асинхронных действий параллельно (редактировать: если вам нужноих результаты)
...