Цепочки обещания .then (): второй. Затем бег перед первым ?? o.0 - PullRequest
0 голосов
/ 30 сентября 2019

Я пытаюсь создать новый объект File из данных BLOB-объектов в структуре .then, а после во втором .then прочитать информацию об этом файле.

Но второй затем запустить до первогоконец, поэтому объект файла еще не заполнен.

Это нормальное поведение? Должен ли я сделать асинхронную функцию, вызываемую в первой, а затем, чтобы убедиться, что вторая вызывается строго после?

      let output = {file: {}, file_infos: {}},
          image = FileAPI.Image(src_file);
      await Promise.all(Object.keys(parameters).map(async (parameter_name) => { // Pass file threw all modifiers (resizing, rotation, overlaying)
        try {
          image = await FileMethods[parameter_name](image, parameters[parameter_name]);
            return image;
        }
        catch(err) {
          console.log(err);
        };
      }))
      .then((output_image) => {
        output_image[0].toBlob((blob) => {
          output.file = new File([blob], src_file.name); // Need this to be fullfilled before step2
          console.log('step1');
        });
      })
      .then(() => {
        console.log('step2');
        FileAPI.getInfo(output.file, (err/**String*/, infos/**Object*/) => {
          if( !err ){
            output.file_infos = infos;
          } else {
            console.log("this is triggered because output.file isn't filled yet");
          }
        })
      });
      // console.log(output);
      return output;

консоль показывает мне:

step2 this is triggered because output.file isn't filled yet step1

Спасибо за помощь:)

Ответы [ 3 ]

2 голосов
/ 30 сентября 2019

Две асинхронные функции в двух .then не возвращают Promise, поэтому сначала их нужно также "Promisified", поскольку вы уже используете async/await, не используйте обещание .then chain

const image = FileAPI.Image(src_file);
const output_image = await Promise.all(Object.keys(parameters).map(async(parameter_name) => {
    try {
        image = await FileMethods[parameter_name](image, parameters[parameter_name]);
        return image;
    } catch (err) {
        console.log(err);
    };
}));
const file = await new Promise((resolve, reject) => output_image[0].toBlob((blob) => 
    resolve(new File([blob], src_file.name))
));
const file_infos = await new Promise((resolve, reject) => FileAPI.getInfo(file, (err, file_infos) => {
    if (!err) {
        resolve(file_infos);
    } else {
        reject("this is triggered because output.file isn't filled yet");
    }
));
return {file, file_infos};

Примечание о

const output_image = await Promise.all(Object.keys(parameters).map(async(parameter_name) => {
    try {
        image = await FileMethods[parameter_name](image, parameters[parameter_name]);
        return image;
    } catch (err) {
        console.log(err);
    };
}));

, по сути, вы делаете return await FileMethods[parameter_name](image, parameters[parameter_name]) - так что вам действительно не нужен в этом случае асинхронный / ожидающий шаблон, простовернуть Обещание в .map

const output_image = await Promise.all(Object.keys(parameters).map((parameter_name) => 
    FileMethods[parameter_name](image, parameters[parameter_name]);
));

Или, что еще приятнее (на мой взгляд)

const output_image = await Promise.all(Object.entries(parameters).map((p_name, p_value) =>
    FileMethods[p_name](image, p_value)
));

В качестве альтернативы, использовать цепи Promise .then и нетasync / await

const image = FileAPI.Image(src_file);
return Promise.all(Object.keys(parameters).map(parameter_name => FileMethods[parameter_name](image, parameters[parameter_name])))
.then(output_image => new Promise((resolve, reject) => output_image[0].toBlob((blob) => 
    resolve(new File([blob], src_file.name))
)))
.then(file => new Promise((resolve, reject) => FileAPI.getInfo(file, (err, file_infos) => {
    if (!err) {
        resolve({file, file_infos});
    } else {
        reject("this is triggered because output.file isn't filled yet");
    }
)));
1 голос
/ 30 сентября 2019

.toBlob() возвращается мгновенно, потому что используется асинхронный шаблон обратного вызова.

Вам нужно вернуть обещание, которое разрешается после завершения работы. Таким образом, вы можете сделать что-то вроде этого:

.then((output_image) => {
    return new Promise((res, rej) => {
      output_image[0].toBlob((blob) => {
        output.file = new File([blob], src_file.name); // Need this to be fullfilled before step2
        console.log('step1');
        res();
      });
    });
  })
1 голос
/ 30 сентября 2019

toBlob возможно асинхронный. Измените первое значение .then на следующее:

.then((output_image) => {
  return new Promise((resolve) => output_image[0].toBlob((blob) => {
    output.file = new File([blob], src_file.name); // Need this to be fullfilled before step2
    console.log('step1');
    resolve();
  }));
})
...