2016-07-19 2 views
0

Я пытаюсь загрузить файл на удаленный сервер, получить путь для этого файла на этом сервере, а затем сохранить его в записи в свой собственный API. В течение более половины времени код выходит из строя, потому что возвращенныйNewFile не определен (хотя я проверил console.log (newFile) в предыдущей функции .then(), и это всегда объект обещания. Что может быть причиной такого поведения? returnedNewFile иногда быть нулевым/неопределенным? Я использую Django REST + Джанго-отдых-JSON-апи + ember.js 2.6, и этот код в JavaScript файле компонента при его. Спасибо заранее!Javascript Promise Chaining Issues (Ember)

store.findRecord('file', folderid).then(function(folder) { 
    var file = fileList.pop(); 
    var newFile = fm.uploadFile(folder, file.name, file); 
    return newFile; 

    }).then(function(returnedNewFile) { 
    var name = returnedNewFile.get('name'); 
    var path = returnedNewFile.get('path'); 
    var doc = store.createRecord('document', { 
     name: name, 
     path: path, 
    }); 
    console.log("doc: ", doc); 
    doc.save(); 
    return doc; 

    }).then(function(doc) { 
    console.log("hi number three"); 
    var grant = store.createRecord('grant', { 
     department: department, 
     number: number, 
     document: doc, 

    }); 
    grant.save(); 
    return grant; 

    }).then(null, function(error) { 
    console.log("Oops: " + error.message) 
    }); 

EDIT: Вот код для uploadFile() (waterbutler это имя файлового сервера, используемого на внешнем сервере (link)):

uploadFile(folder, name, contents, options = {}) { 
    let url = folder.get('links').upload; 
    options.data = contents; 
    if (!options.query) { 
     options.query = {}; 
    } 
    options.query.name = name; 
    options.query.kind = 'file'; 

    let p = this._waterbutlerRequest('PUT', url, options); 
    return p.then(() => this._getNewFileInfo(folder, name)); 
} 

А вот код для _getNewFileInfo:

/** 
* Get the `file` model for a newly created file. 
* 
* @method _getNewFileInfo 
* @private 
* @param {file} parentFolder Model for the new file's parent folder. 
* @param {String} name Name of the new file. 
* @return {Promise} Promise that resolves to the new file's model or 
* rejects with an error message. 
*/ 
_getNewFileInfo(parentFolder, name) { 
    let p = this._reloadModel(parentFolder.get('files')); 
    return p.then((files) => files.findBy('name', name)); 
} 
+0

Не будет ли 'fm.uploadFile()' быть асинхронным? Какой модуль node.js работает, чтобы мы могли посмотреть на документ? – jfriend00

+0

[Здесь] (https://github.com/CenterForOpenScience/ember-osf/blob/develop/addon/services/file-manager.js) ссылка на класс файлового менеджера (fm). 'fm.uploadFile()' является асинхронным, но у меня создалось впечатление, что такая цепочка - это то, как вы это учитываете. Похоже, я могу быть, хотя. – Cameron

+1

Это всегда может быть экземпляр «Promise», но иногда это может быть обещание, которое выполняет «неопределенный». Покажите нам, что делает '_getNewFileInfo'. – Bergi

ответ

1

Более половины времени, происходит сбой кода, поскольку returnedNewFile является неопределенным (хотя я проверил console.log (NewFile) в предыдущем .then (), и это всегда объект обещания. Что может быть причиной ?

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

Так что если вы позвонили newFile.then(function(newFileResult) { ..., тогда newFileResult будет таким же, как то, что вы сейчас получаете в приведенном выше коде, как аргумент returnedNewFile. Почему обещания этой библиотеки иногда возвращаются с значением undefined вне меня.

EDIT: Не совсем понял комментарий, поэтому пример. У меня есть функция, называемая getText(str), которая асинхронно извлекает эту строку.

response1 = getText("abc").then(ignoredStr => { 
    return "def"; 
}); 

response2 = getText("abc").then(ignoredStr => { 
    return getText("def"); 
}); 

response1.then(function(str1) { 
    // "def" 
}); 

response2.then(function(str2) { 
    // "def" 
}); 

при определенном понимании обещаний, str2 будет Promise вместо string; но это не так. Он видит, что он получил обещание, а не «ценность», и ждет этого, прежде чем связать вызов .then(). Даже если getText («def») вернется через 3 секунды, он будет ждать еще 3 секунды для второго вызова, прежде чем дать нам результат .then().

+0

Решив это второе обещание, вы имеете в виду принудительное решение проблемы немедленно или дождаться его разрешения? Прошу прощения, если это глупый вопрос. Все еще пытаясь понять нюансы асинхронности. – Cameron

+0

@Cameron Я добавил пример, надеюсь, что это поможет понять. – Katana314