似乎我对await
的使用并不像我理解的那样。
我认为async
函数和await
关键字可用于返回promise的调用(例如navigator.mediaDevices.getUserMedia
),它会暂停函数执行(如生成器函数)直到promise解决,然后它将继续使用该函数。
即使我正在等待电话,它立即返回,我的控制台日志也发生了故障。特别是控制台日志以" reducer"开头。出现在" getter"之前的控制台中,当它应该是相反的方式/与我认为堆栈跟踪应该如何运行相反。
谁能告诉我这里发生了什么?
异步辅助函数getter:
const getLocalStream = async () => {
try {
const localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
console.log('getter localStream', localStream);
console.log('about to return')
return localStream;
}
catch (err) {
console.error(err);
}
}
export default getLocalStream;
Reducer / store:
import getLocalStream from './getLocalStream';
const reducer = (state = {}, action) => {
switch (action.type) {
case 'SEND_CALL': {
const { id } = action;
const localStream = getLocalStream();
console.log('reducer localStream', localStream);
const call = state.peer.call(id, localStream);
return { ...state, call };
}
default:
return state;
}
};
控制台:
reducer localStream Promise {<pending>}
Uncaught TypeError: Failed to execute 'addStream' on 'RTCPeerConnection': parameter 1 is not of type 'MediaStream'
getter localStream MediaStream {id: "B6Foz1jheGvnMqjiqC4PFoOvUVahF04zigzm", active: true, onaddtrack: null, onremovetrack: null, onactive: null, …}
about to return
答案 0 :(得分:2)
使用redx-thunk。由于您的reducer必须返回一个新状态,因此您无法在reducer中执行异步操作。
您可以在中间件中进行异步操作,这样您就可以自己编写中间件或使用redux-thunk。
如果您发送一个函数动作,那么thunk将使用AdapterNotification.java
和package com.myapp.adapter;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.support.v7.widget.RecyclerView;
import android.text.format.DateUtils;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.material.nereeducation.R;
import com.material.nereeducation.helper.AlphabetColor;
import com.material.nereeducation.model.Notification;
import com.material.nereeducation.utils.Tools;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class AdapterNotification extends RecyclerView.Adapter<AdapterNotification.ViewHolder> {
private Context ctx;
private List<Notification> items;
private OnClickListener onClickListener = null;
private SparseBooleanArray selected_items;
private int current_selected_idx = -1;
private AlphabetColor alphabetColor;
public void setOnClickListener(OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView from, title, message, date, image_letter;
public ImageView image;
public RelativeLayout lyt_checked, lyt_image;
public View lyt_parent;
public ViewHolder(View view) {
super(view);
from = view.findViewById(R.id.from);
title = view.findViewById(R.id.title);
message = view.findViewById(R.id.message);
date = view.findViewById(R.id.date);
image_letter = view.findViewById(R.id.image_letter);
image = view.findViewById(R.id.image);
lyt_checked = view.findViewById(R.id.lyt_checked);
lyt_image = view.findViewById(R.id.lyt_image);
lyt_parent = view.findViewById(R.id.lyt_parent);
}
}
public AdapterNotification(Context mContext, List<Notification> items) {
this.ctx = mContext;
this.items = items;
selected_items = new SparseBooleanArray();
alphabetColor = new AlphabetColor(mContext);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_notification, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final Notification notification = items.get(position);
// displaying text view data
System.out.println("sender type:"+notification.sender_type);
Character firstLetter;
if(notification.sender_type.equals("1")) //Admin
{
String admin = ctx.getString(R.string.admin_name);
holder.from.setText(admin);
firstLetter = admin.substring(0, 1).charAt(0);
holder.image_letter.setText(String.valueOf(firstLetter));
}else
{
holder.from.setText(notification.senderName);
firstLetter = notification.senderName.substring(0, 1).charAt(0);
holder.image_letter.setText(String.valueOf(firstLetter));
}
if(notification.status.equals("unread"))
{
holder.from.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
holder.title.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
}
holder.title.setText(notification.title);
holder.message.setText(notification.message);
holder.date.setText(getDate(Long.parseLong(notification.date)));
holder.lyt_parent.setActivated(selected_items.get(position, false));
holder.lyt_parent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onClickListener == null) return;
onClickListener.onItemClick(v, notification, position);
}
});
holder.lyt_parent.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onClickListener == null) return false;
onClickListener.onItemLongClick(v, notification, position);
return true;
}
});
toggleCheckedIcon(holder, position);
displayImage(holder, notification, firstLetter);
}
private void displayImage(ViewHolder holder, Notification notification, Character firstLetter) {
if (notification.image != null) {
Tools.displayImageRound(ctx, holder.image, notification.image);
holder.image.setColorFilter(null);
holder.image_letter.setVisibility(View.GONE);
} else {
holder.image.setImageResource(R.drawable.shape_circle);
holder.image.setColorFilter(alphabetColor.getColorByAlphabet(firstLetter), PorterDuff.Mode.MULTIPLY);
holder.image_letter.setVisibility(View.VISIBLE);
}
}
private String getDate(long time) {
Date date = new Date();
long currentTime = date.getTime();
String result = (String) DateUtils.getRelativeTimeSpanString(time, currentTime, 0);
return result;
}
private void toggleCheckedIcon(ViewHolder holder, int position) {
if (selected_items.get(position, false)) {
holder.lyt_image.setVisibility(View.GONE);
holder.lyt_checked.setVisibility(View.VISIBLE);
if (current_selected_idx == position) resetCurrentIndex();
} else {
holder.lyt_checked.setVisibility(View.GONE);
holder.lyt_image.setVisibility(View.VISIBLE);
if (current_selected_idx == position) resetCurrentIndex();
}
}
public Notification getItem(int position) {
return items.get(position);
}
@Override
public int getItemCount() {
return items.size();
}
public void toggleSelection(int pos) {
current_selected_idx = pos;
if (selected_items.get(pos, false)) {
selected_items.delete(pos);
} else {
selected_items.put(pos, true);
}
notifyItemChanged(pos);
}
public void clearSelections() {
selected_items.clear();
notifyDataSetChanged();
}
public int getSelectedItemCount() {
return selected_items.size();
}
public List<Integer> getSelectedItems() {
List<Integer> items = new ArrayList<>(selected_items.size());
for (int i = 0; i < selected_items.size(); i++) {
items.add(selected_items.keyAt(i));
}
return items;
}
public void removeData(int position) {
items.remove(position);
resetCurrentIndex();
}
private void resetCurrentIndex() {
current_selected_idx = -1;
}
public interface OnClickListener {
void onItemClick(View view, Notification obj, int pos);
void onItemLongClick(View view, Notification obj, int pos);
}
}
函数执行该函数。
dispatch
Thunk将简化异步中间件或需要分派多个操作的操作。
如何解释redux的工作方式以及中间件如何工作here它正在调用reducer“应用程序处理函数”,因为我将它作为事件存储而不是针对redux特定的。
为什么redux不接受promises作为状态并且只是在结算时设置状态的原因可以找到here。当一个待处理的过滤器请求被来自用户的较新请求替换时,挂起的过滤器将拒绝,这应该发生什么但是redux如何知道该承诺应该拒绝?因此,如果我们必须解决那么,当旧的待处理请求解决时,我们如何告诉redux不要设置状态?这些问题基本上可以通过reducer不返回promise并在中间件中处理它来解决。
答案 1 :(得分:1)
您需要await
调用减速器中的async
功能。
现在,你打电话给它,但绝不等待它完成。
答案 2 :(得分:1)
您也需要在async/await
函数中使用reducer
,否则getLocalStream()
将只返回promise
个实例。
这是因为,根据docs,
当调用异步函数时,它返回一个Promise。当异步函数返回一个值时,将使用返回的值解析Promise。当异步函数抛出异常或某个值时,将使用抛出的值拒绝Promise。
异步函数可以包含一个等待表达式,它会暂停 执行异步函数并等待传递的Promise 解析,然后恢复异步函数的执行和 返回已解析的值。
const reducer = async (state = {}, action) => { //HERE
switch (action.type) {
case 'SEND_CALL': {
const { id } = action;
const localStream = await getLocalStream(); //HERE
console.log('reducer localStream', localStream);
const call = state.peer.call(id, localStream);
return { ...state, call };
}
default:
return state;
}
};