Правильная обработка обещаний с модульным JS, могу ли я ссылаться на один и тот же Promise.then () более одного раза? - PullRequest
0 голосов
/ 07 мая 2019

Это мой первый вопрос о переполнении стека, и я впервые создаю приложение, предназначенное для публичного использования. Так что прости меня, если этот вопрос кажется открытым для интерпретации со многими конкретными ответами. Опять же, я могу все делать неправильно!

У меня есть SPA, использующий модули ES6 с Webpack и переносящий с помощью Babel.

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

Я использую jQuery.ajax, обернутый в Обещание.

У меня есть модуль, который является IIFE. Я не уверен, что это хорошая практика.

iife.modular.promise.js

export default (function(){
    // console.log('iife.modular.promise.js is invoked when app is parsed');

    function AjaxPromise(options) {

        // console.log ('Promise invoked, get response');

        return new Promise(function (resolve, reject) {
            jQuery.ajax(options).done(resolve).fail(reject);
        });

    }

    return AjaxPromise({
        url: YOUR_URL,
        type: 'post',
        data: {
          action: get_some_data
        }

    })
}())


Затем я могу обратиться к нему в другом модуле.

index.js

import { default as modPromise } from './iife.modular.promise.js'
import { startApp } from './startApp.js'

modPromise.then( (response)=>{
  // return response data and do stuff.
  console.log(response)
  // EG
  // {
  //   success: true,
  //   data: "Hello World!"   
  // }

  // run application
  startApp()

});

Кажется, это работает без проблем. Однако ответ от обещания (ей) необходим для настройки начального состояния объектов, на которые затем ссылаются различные модули.

puzzle.js

import { default as modPromise } from'./iife.modular.promise.js'

class Puzzle {
    constructor(name, level, [args]) {
        this.name = name;
        this.level = level;
        this.puzzleSpec = [args]
    }

    isInit() {
        return `class initialised`;
    }
}

// closure
var puzzleInit;

modPromise.then( (response)=>{
  // my response data actually evaluates to an array
  let data = JSON.parse(response.data)
  // instantiate class.
  puzzleInit = new Puzzle ( ...data )
});

export { puzzleInit }

Когда Обещание выполнено, модуль puzzle.js ссылается на объект / класс Puzzle.

Это то место, где я обеспокоен. Я дважды ссылаюсь на одно и то же Обещание и вызываю метод .then() в двух отдельных модулях.

puzzle.js для создания нового экземпляра объекта.

index.js для использования в качестве потока управления . Не запускайте приложение, пока не будет создан экземпляр puzzle.js.

Кажется, это не дает никаких справочных ошибок. Я не понимаю, почему это должно быть проблемой, учитывая, что iife.modular.promise.js вызывается только один раз и возвращает объект Promise, на который можно предположительно ссылаться много раз.

Может оказаться более эффективным НЕ использовать модульный IIFE, возвращающий обещание. IE использует объявление / выражение функции, которое вызывается только один раз.

onTheFly.modular.promise.js

function onTheFly(){

    function AjaxPromise(options) {

        return new Promise(function (resolve, reject) {
            jQuery.ajax(options).done(resolve).fail(reject);
        });

    }

    return AjaxPromise({
        url: YOUR_URL,
        type: 'post',
        data: {
          action: get_some_data
        }

    })
}

export { onTheFly }

Однако, так как каждый раз, когда onTheFlyPromise() вызывается в модуле, будет сделано новое обещание / запрос. Это означает, что для совместного использования response.data между различными модулями данные должны храниться в выделенном модуле.

Возможный способ обойти это будет использовать Promise.all()

many.promises.js

const manyPromise = function(args){

    return Promise.all(args);
}

export { manyPromise };

index.js

import { default as modPromise } from './modular.promise.js'
import { onTheFlyPromise } from './onTheFly.modular.promise.js'
// Promise All
import { manyPromise } from './manyPromise.js'

import { startApp } from './startApp.js'

const multiplePromises = manyPromise(modPromise, onTheFlyPromise() ); 

multiplePromises.then( (response)=>{
  // return response data from all promises and do stuff.
  console.log(response)

// EG [{ },{ }]

  // run application
  startApp()

});

Кажется, что все эти опции имеют потенциал и не вызывают сбой в приложении, которое я создаю.

Я не обращаю особого внимания на то, когда Обещания вызываются и являются ли они асинхронными. Я предполагаю, что, поскольку я использую jQuery.ajax, они не являются действительно асинхронными Обещаниями?

Любой совет будет высоко ценится.

1 Ответ

1 голос
/ 07 мая 2019

У меня есть модуль, который является IIFE. Я не уверен, что это хорошая практика.

Нет необходимости, если вы используете модули ES2015, как вы и сказали. Модуль имеет свою область применения.

Это то место, где я обеспокоен. Я дважды ссылаюсь на одно и то же Обещание и вызываю метод .then () в двух отдельных модулях.

Это абсолютно нормально, в этом нет ничего плохого. Несколько потребителей могут использовать одно и то же обещание. Они все увидят одно и то же значение разрешения (или причину отклонения). И это не проблема, если обещание уже выполнено до того, как потребители позвонят then или catch.

Обратите внимание, что в вашем обещании отсутствуют обработчики отклонений. Одно из правил использования обещаний: либо обрабатывать ошибки (через catch или второй аргумент then), либо передавать результат then чему-то, что будет обрабатывать ошибки.


Примечание:

import { default as modPromise } from './modular.promise.js'

Хотя это работает, более идиоматичный способ импорта экспорта по умолчанию:

import modPromise from './modular.promise.js';
...